s3:include: make smb_setlen() a macro
[vlendec/samba-autobuild/.git] / source3 / lib / util.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Samba utility functions
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Jeremy Allison 2001-2007
6    Copyright (C) Simo Sorce 2001
7    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
8    Copyright (C) James Peach 2006
9
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.
14
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.
19
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/>.
22 */
23
24 #include "includes.h"
25 #include "system/passwd.h"
26 #include "system/filesys.h"
27 #include "util_tdb.h"
28 #include "ctdbd_conn.h"
29 #include "../lib/util/util_pw.h"
30 #include "messages.h"
31 #include <ccan/hash/hash.h>
32 #include "libcli/security/security.h"
33
34 #ifdef HAVE_SYS_PRCTL_H
35 #include <sys/prctl.h>
36 #endif
37
38 /* Max allowable allococation - 256mb - 0x10000000 */
39 #define MAX_ALLOC_SIZE (1024*1024*256)
40
41 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
42 #ifdef WITH_NISPLUS_HOME
43 #ifdef BROKEN_NISPLUS_INCLUDE_FILES
44 /*
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.
50  */
51
52 #if defined(GROUP)
53 #undef GROUP
54 #endif
55
56 #if defined(GROUP_OBJ)
57 #undef GROUP_OBJ
58 #endif
59
60 #endif /* BROKEN_NISPLUS_INCLUDE_FILES */
61
62 #include <rpcsvc/nis.h>
63
64 #endif /* WITH_NISPLUS_HOME */
65 #endif /* HAVE_NETGROUP && WITH_AUTOMOUNT */
66
67 static enum protocol_types Protocol = PROTOCOL_COREPLUS;
68
69 enum protocol_types get_Protocol(void)
70 {
71         return Protocol;
72 }
73
74 void set_Protocol(enum protocol_types  p)
75 {
76         Protocol = p;
77 }
78
79 static enum remote_arch_types ra_type = RA_UNKNOWN;
80
81 void gfree_all( void )
82 {
83         gfree_names();
84         gfree_loadparm();
85         gfree_charcnv();
86         gfree_interfaces();
87         gfree_debugsyms();
88 }
89
90 /*******************************************************************
91  Check if a file exists - call vfs_file_exist for samba files.
92 ********************************************************************/
93
94 bool file_exist_stat(const char *fname,SMB_STRUCT_STAT *sbuf,
95                      bool fake_dir_create_times)
96 {
97         SMB_STRUCT_STAT st;
98         if (!sbuf)
99                 sbuf = &st;
100
101         if (sys_stat(fname, sbuf, fake_dir_create_times) != 0)
102                 return(False);
103
104         return((S_ISREG(sbuf->st_ex_mode)) || (S_ISFIFO(sbuf->st_ex_mode)));
105 }
106
107 /*******************************************************************
108  Check if a unix domain socket exists - call vfs_file_exist for samba files.
109 ********************************************************************/
110
111 bool socket_exist(const char *fname)
112 {
113         SMB_STRUCT_STAT st;
114         if (sys_stat(fname, &st, false) != 0)
115                 return(False);
116
117         return S_ISSOCK(st.st_ex_mode);
118 }
119
120 /*******************************************************************
121  Returns the size in bytes of the named given the stat struct.
122 ********************************************************************/
123
124 uint64_t get_file_size_stat(const SMB_STRUCT_STAT *sbuf)
125 {
126         return sbuf->st_ex_size;
127 }
128
129 /*******************************************************************
130  Returns the size in bytes of the named file.
131 ********************************************************************/
132
133 SMB_OFF_T get_file_size(char *file_name)
134 {
135         SMB_STRUCT_STAT buf;
136         buf.st_ex_size = 0;
137         if (sys_stat(file_name, &buf, false) != 0)
138                 return (SMB_OFF_T)-1;
139         return get_file_size_stat(&buf);
140 }
141
142 /*******************************************************************
143  Show a smb message structure.
144 ********************************************************************/
145
146 void show_msg(const char *buf)
147 {
148         int i;
149         int bcc=0;
150
151         if (!DEBUGLVL(5))
152                 return;
153
154         DEBUG(5,("size=%d\nsmb_com=0x%x\nsmb_rcls=%d\nsmb_reh=%d\nsmb_err=%d\nsmb_flg=%d\nsmb_flg2=%d\n",
155                         smb_len(buf),
156                         (int)CVAL(buf,smb_com),
157                         (int)CVAL(buf,smb_rcls),
158                         (int)CVAL(buf,smb_reh),
159                         (int)SVAL(buf,smb_err),
160                         (int)CVAL(buf,smb_flg),
161                         (int)SVAL(buf,smb_flg2)));
162         DEBUGADD(5,("smb_tid=%d\nsmb_pid=%d\nsmb_uid=%d\nsmb_mid=%d\n",
163                         (int)SVAL(buf,smb_tid),
164                         (int)SVAL(buf,smb_pid),
165                         (int)SVAL(buf,smb_uid),
166                         (int)SVAL(buf,smb_mid)));
167         DEBUGADD(5,("smt_wct=%d\n",(int)CVAL(buf,smb_wct)));
168
169         for (i=0;i<(int)CVAL(buf,smb_wct);i++)
170                 DEBUGADD(5,("smb_vwv[%2d]=%5d (0x%X)\n",i,
171                         SVAL(buf,smb_vwv+2*i),SVAL(buf,smb_vwv+2*i)));
172
173         bcc = (int)SVAL(buf,smb_vwv+2*(CVAL(buf,smb_wct)));
174
175         DEBUGADD(5,("smb_bcc=%d\n",bcc));
176
177         if (DEBUGLEVEL < 10)
178                 return;
179
180         if (DEBUGLEVEL < 50)
181                 bcc = MIN(bcc, 512);
182
183         dump_data(10, (const uint8 *)smb_buf_const(buf), bcc);
184 }
185
186 /*******************************************************************
187  Setup only the byte count for a smb message.
188 ********************************************************************/
189
190 int set_message_bcc(char *buf,int num_bytes)
191 {
192         int num_words = CVAL(buf,smb_wct);
193         SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
194         _smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
195         return (smb_size + num_words*2 + num_bytes);
196 }
197
198 /*******************************************************************
199  Add a data blob to the end of a smb_buf, adjusting bcc and smb_len.
200  Return the bytes added
201 ********************************************************************/
202
203 ssize_t message_push_blob(uint8 **outbuf, DATA_BLOB blob)
204 {
205         size_t newlen = smb_len(*outbuf) + 4 + blob.length;
206         uint8 *tmp;
207
208         if (!(tmp = talloc_realloc(NULL, *outbuf, uint8, newlen))) {
209                 DEBUG(0, ("talloc failed\n"));
210                 return -1;
211         }
212         *outbuf = tmp;
213
214         memcpy(tmp + smb_len(tmp) + 4, blob.data, blob.length);
215         set_message_bcc((char *)tmp, smb_buflen(tmp) + blob.length);
216         return blob.length;
217 }
218
219 /*******************************************************************
220  Reduce a file name, removing .. elements.
221 ********************************************************************/
222
223 static char *dos_clean_name(TALLOC_CTX *ctx, const char *s)
224 {
225         char *p = NULL;
226         char *str = NULL;
227
228         DEBUG(3,("dos_clean_name [%s]\n",s));
229
230         /* remove any double slashes */
231         str = talloc_all_string_sub(ctx, s, "\\\\", "\\");
232         if (!str) {
233                 return NULL;
234         }
235
236         /* Remove leading .\\ characters */
237         if(strncmp(str, ".\\", 2) == 0) {
238                 trim_string(str, ".\\", NULL);
239                 if(*str == 0) {
240                         str = talloc_strdup(ctx, ".\\");
241                         if (!str) {
242                                 return NULL;
243                         }
244                 }
245         }
246
247         while ((p = strstr_m(str,"\\..\\")) != NULL) {
248                 char *s1;
249
250                 *p = 0;
251                 s1 = p+3;
252
253                 if ((p=strrchr_m(str,'\\')) != NULL) {
254                         *p = 0;
255                 } else {
256                         *str = 0;
257                 }
258                 str = talloc_asprintf(ctx,
259                                 "%s%s",
260                                 str,
261                                 s1);
262                 if (!str) {
263                         return NULL;
264                 }
265         }
266
267         trim_string(str,NULL,"\\..");
268         return talloc_all_string_sub(ctx, str, "\\.\\", "\\");
269 }
270
271 /*******************************************************************
272  Reduce a file name, removing .. elements.
273 ********************************************************************/
274
275 char *unix_clean_name(TALLOC_CTX *ctx, const char *s)
276 {
277         char *p = NULL;
278         char *str = NULL;
279
280         DEBUG(3,("unix_clean_name [%s]\n",s));
281
282         /* remove any double slashes */
283         str = talloc_all_string_sub(ctx, s, "//","/");
284         if (!str) {
285                 return NULL;
286         }
287
288         /* Remove leading ./ characters */
289         if(strncmp(str, "./", 2) == 0) {
290                 trim_string(str, "./", NULL);
291                 if(*str == 0) {
292                         str = talloc_strdup(ctx, "./");
293                         if (!str) {
294                                 return NULL;
295                         }
296                 }
297         }
298
299         while ((p = strstr_m(str,"/../")) != NULL) {
300                 char *s1;
301
302                 *p = 0;
303                 s1 = p+3;
304
305                 if ((p=strrchr_m(str,'/')) != NULL) {
306                         *p = 0;
307                 } else {
308                         *str = 0;
309                 }
310                 str = talloc_asprintf(ctx,
311                                 "%s%s",
312                                 str,
313                                 s1);
314                 if (!str) {
315                         return NULL;
316                 }
317         }
318
319         trim_string(str,NULL,"/..");
320         return talloc_all_string_sub(ctx, str, "/./", "/");
321 }
322
323 char *clean_name(TALLOC_CTX *ctx, const char *s)
324 {
325         char *str = dos_clean_name(ctx, s);
326         if (!str) {
327                 return NULL;
328         }
329         return unix_clean_name(ctx, str);
330 }
331
332 /*******************************************************************
333  Write data into an fd at a given offset. Ignore seek errors.
334 ********************************************************************/
335
336 ssize_t write_data_at_offset(int fd, const char *buffer, size_t N, SMB_OFF_T pos)
337 {
338         size_t total=0;
339         ssize_t ret;
340
341         if (pos == (SMB_OFF_T)-1) {
342                 return write_data(fd, buffer, N);
343         }
344 #if defined(HAVE_PWRITE) || defined(HAVE_PRWITE64)
345         while (total < N) {
346                 ret = sys_pwrite(fd,buffer + total,N - total, pos);
347                 if (ret == -1 && errno == ESPIPE) {
348                         return write_data(fd, buffer + total,N - total);
349                 }
350                 if (ret == -1) {
351                         DEBUG(0,("write_data_at_offset: write failure. Error = %s\n", strerror(errno) ));
352                         return -1;
353                 }
354                 if (ret == 0) {
355                         return total;
356                 }
357                 total += ret;
358                 pos += ret;
359         }
360         return (ssize_t)total;
361 #else
362         /* Use lseek and write_data. */
363         if (sys_lseek(fd, pos, SEEK_SET) == -1) {
364                 if (errno != ESPIPE) {
365                         return -1;
366                 }
367         }
368         return write_data(fd, buffer, N);
369 #endif
370 }
371
372
373 NTSTATUS reinit_after_fork(struct messaging_context *msg_ctx,
374                            struct event_context *ev_ctx,
375                            struct server_id id,
376                            bool parent_longlived)
377 {
378         NTSTATUS status = NT_STATUS_OK;
379
380         /* Reset the state of the random
381          * number generation system, so
382          * children do not get the same random
383          * numbers as each other */
384         set_need_random_reseed();
385
386         /* tdb needs special fork handling */
387         if (tdb_reopen_all(parent_longlived ? 1 : 0) != 0) {
388                 DEBUG(0,("tdb_reopen_all failed.\n"));
389                 status = NT_STATUS_OPEN_FAILED;
390                 goto done;
391         }
392
393         if (ev_ctx && tevent_re_initialise(ev_ctx) != 0) {
394                 smb_panic(__location__ ": Failed to re-initialise event context");
395         }
396
397         if (msg_ctx) {
398                 /*
399                  * For clustering, we need to re-init our ctdbd connection after the
400                  * fork
401                  */
402                 status = messaging_reinit(msg_ctx, id);
403                 if (!NT_STATUS_IS_OK(status)) {
404                         DEBUG(0,("messaging_reinit() failed: %s\n",
405                                  nt_errstr(status)));
406                 }
407         }
408  done:
409         return status;
410 }
411
412 /****************************************************************************
413  (Hopefully) efficient array append.
414 ****************************************************************************/
415
416 void add_to_large_array(TALLOC_CTX *mem_ctx, size_t element_size,
417                         void *element, void *_array, uint32 *num_elements,
418                         ssize_t *array_size)
419 {
420         void **array = (void **)_array;
421
422         if (*array_size < 0) {
423                 return;
424         }
425
426         if (*array == NULL) {
427                 if (*array_size == 0) {
428                         *array_size = 128;
429                 }
430
431                 if (*array_size >= MAX_ALLOC_SIZE/element_size) {
432                         goto error;
433                 }
434
435                 *array = TALLOC(mem_ctx, element_size * (*array_size));
436                 if (*array == NULL) {
437                         goto error;
438                 }
439         }
440
441         if (*num_elements == *array_size) {
442                 *array_size *= 2;
443
444                 if (*array_size >= MAX_ALLOC_SIZE/element_size) {
445                         goto error;
446                 }
447
448                 *array = TALLOC_REALLOC(mem_ctx, *array,
449                                         element_size * (*array_size));
450
451                 if (*array == NULL) {
452                         goto error;
453                 }
454         }
455
456         memcpy((char *)(*array) + element_size*(*num_elements),
457                element, element_size);
458         *num_elements += 1;
459
460         return;
461
462  error:
463         *num_elements = 0;
464         *array_size = -1;
465 }
466
467 /****************************************************************************
468  Get my own domain name, or "" if we have none.
469 ****************************************************************************/
470
471 char *get_mydnsdomname(TALLOC_CTX *ctx)
472 {
473         const char *domname;
474         char *p;
475
476         domname = get_mydnsfullname();
477         if (!domname) {
478                 return NULL;
479         }
480
481         p = strchr_m(domname, '.');
482         if (p) {
483                 p++;
484                 return talloc_strdup(ctx, p);
485         } else {
486                 return talloc_strdup(ctx, "");
487         }
488 }
489
490 /****************************************************************************
491  Interpret a protocol description string, with a default.
492 ****************************************************************************/
493
494 int interpret_protocol(const char *str,int def)
495 {
496         if (strequal(str,"NT1"))
497                 return(PROTOCOL_NT1);
498         if (strequal(str,"LANMAN2"))
499                 return(PROTOCOL_LANMAN2);
500         if (strequal(str,"LANMAN1"))
501                 return(PROTOCOL_LANMAN1);
502         if (strequal(str,"CORE"))
503                 return(PROTOCOL_CORE);
504         if (strequal(str,"COREPLUS"))
505                 return(PROTOCOL_COREPLUS);
506         if (strequal(str,"CORE+"))
507                 return(PROTOCOL_COREPLUS);
508
509         DEBUG(0,("Unrecognised protocol level %s\n",str));
510
511         return(def);
512 }
513
514
515 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
516 /******************************************************************
517  Remove any mount options such as -rsize=2048,wsize=2048 etc.
518  Based on a fix from <Thomas.Hepper@icem.de>.
519  Returns a malloc'ed string.
520 *******************************************************************/
521
522 static char *strip_mount_options(TALLOC_CTX *ctx, const char *str)
523 {
524         if (*str == '-') {
525                 const char *p = str;
526                 while(*p && !isspace(*p))
527                         p++;
528                 while(*p && isspace(*p))
529                         p++;
530                 if(*p) {
531                         return talloc_strdup(ctx, p);
532                 }
533         }
534         return NULL;
535 }
536
537 /*******************************************************************
538  Patch from jkf@soton.ac.uk
539  Split Luke's automount_server into YP lookup and string splitter
540  so can easily implement automount_path().
541  Returns a malloc'ed string.
542 *******************************************************************/
543
544 #ifdef WITH_NISPLUS_HOME
545 char *automount_lookup(TALLOC_CTX *ctx, const char *user_name)
546 {
547         char *value = NULL;
548
549         char *nis_map = (char *)lp_nis_home_map_name();
550
551         char buffer[NIS_MAXATTRVAL + 1];
552         nis_result *result;
553         nis_object *object;
554         entry_obj  *entry;
555
556         snprintf(buffer, sizeof(buffer), "[key=%s],%s", user_name, nis_map);
557         DEBUG(5, ("NIS+ querystring: %s\n", buffer));
558
559         if (result = nis_list(buffer, FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP, NULL, NULL)) {
560                 if (result->status != NIS_SUCCESS) {
561                         DEBUG(3, ("NIS+ query failed: %s\n", nis_sperrno(result->status)));
562                 } else {
563                         object = result->objects.objects_val;
564                         if (object->zo_data.zo_type == ENTRY_OBJ) {
565                                 entry = &object->zo_data.objdata_u.en_data;
566                                 DEBUG(5, ("NIS+ entry type: %s\n", entry->en_type));
567                                 DEBUG(3, ("NIS+ result: %s\n", entry->en_cols.en_cols_val[1].ec_value.ec_value_val));
568
569                                 value = talloc_strdup(ctx,
570                                                 entry->en_cols.en_cols_val[1].ec_value.ec_value_val);
571                                 if (!value) {
572                                         nis_freeresult(result);
573                                         return NULL;
574                                 }
575                                 value = talloc_string_sub(ctx,
576                                                 value,
577                                                 "&",
578                                                 user_name);
579                         }
580                 }
581         }
582         nis_freeresult(result);
583
584         if (value) {
585                 value = strip_mount_options(ctx, value);
586                 DEBUG(4, ("NIS+ Lookup: %s resulted in %s\n",
587                                         user_name, value));
588         }
589         return value;
590 }
591 #else /* WITH_NISPLUS_HOME */
592
593 char *automount_lookup(TALLOC_CTX *ctx, const char *user_name)
594 {
595         char *value = NULL;
596
597         int nis_error;        /* returned by yp all functions */
598         char *nis_result;     /* yp_match inits this */
599         int nis_result_len;  /* and set this */
600         char *nis_domain;     /* yp_get_default_domain inits this */
601         char *nis_map = (char *)lp_nis_home_map_name();
602
603         if ((nis_error = yp_get_default_domain(&nis_domain)) != 0) {
604                 DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
605                 return NULL;
606         }
607
608         DEBUG(5, ("NIS Domain: %s\n", nis_domain));
609
610         if ((nis_error = yp_match(nis_domain, nis_map, user_name,
611                                         strlen(user_name), &nis_result,
612                                         &nis_result_len)) == 0) {
613                 if (nis_result_len > 0 && nis_result[nis_result_len] == '\n') {
614                         nis_result[nis_result_len] = '\0';
615                 }
616                 value = talloc_strdup(ctx, nis_result);
617                 if (!value) {
618                         return NULL;
619                 }
620                 value = strip_mount_options(ctx, value);
621         } else if(nis_error == YPERR_KEY) {
622                 DEBUG(3, ("YP Key not found:  while looking up \"%s\" in map \"%s\"\n", 
623                                 user_name, nis_map));
624                 DEBUG(3, ("using defaults for server and home directory\n"));
625         } else {
626                 DEBUG(3, ("YP Error: \"%s\" while looking up \"%s\" in map \"%s\"\n", 
627                                 yperr_string(nis_error), user_name, nis_map));
628         }
629
630         if (value) {
631                 DEBUG(4, ("YP Lookup: %s resulted in %s\n", user_name, value));
632         }
633         return value;
634 }
635 #endif /* WITH_NISPLUS_HOME */
636 #endif
637
638 /****************************************************************************
639  Check if a process exists. Does this work on all unixes?
640 ****************************************************************************/
641
642 bool process_exists(const struct server_id pid)
643 {
644         if (procid_is_me(&pid)) {
645                 return True;
646         }
647
648         if (procid_is_local(&pid)) {
649                 return (kill(pid.pid,0) == 0 || errno != ESRCH);
650         }
651
652 #ifdef CLUSTER_SUPPORT
653         return ctdbd_process_exists(messaging_ctdbd_connection(),
654                                     pid.vnn, pid.pid);
655 #else
656         return False;
657 #endif
658 }
659
660 /*******************************************************************
661  Convert a uid into a user name.
662 ********************************************************************/
663
664 const char *uidtoname(uid_t uid)
665 {
666         TALLOC_CTX *ctx = talloc_tos();
667         char *name = NULL;
668         struct passwd *pass = NULL;
669
670         pass = getpwuid_alloc(ctx,uid);
671         if (pass) {
672                 name = talloc_strdup(ctx,pass->pw_name);
673                 TALLOC_FREE(pass);
674         } else {
675                 name = talloc_asprintf(ctx,
676                                 "%ld",
677                                 (long int)uid);
678         }
679         return name;
680 }
681
682 /*******************************************************************
683  Convert a gid into a group name.
684 ********************************************************************/
685
686 char *gidtoname(gid_t gid)
687 {
688         struct group *grp;
689
690         grp = getgrgid(gid);
691         if (grp) {
692                 return talloc_strdup(talloc_tos(), grp->gr_name);
693         }
694         else {
695                 return talloc_asprintf(talloc_tos(),
696                                         "%d",
697                                         (int)gid);
698         }
699 }
700
701 /*******************************************************************
702  Convert a user name into a uid.
703 ********************************************************************/
704
705 uid_t nametouid(const char *name)
706 {
707         struct passwd *pass;
708         char *p;
709         uid_t u;
710
711         pass = Get_Pwnam_alloc(talloc_tos(), name);
712         if (pass) {
713                 u = pass->pw_uid;
714                 TALLOC_FREE(pass);
715                 return u;
716         }
717
718         u = (uid_t)strtol(name, &p, 0);
719         if ((p != name) && (*p == '\0'))
720                 return u;
721
722         return (uid_t)-1;
723 }
724
725 /*******************************************************************
726  Convert a name to a gid_t if possible. Return -1 if not a group. 
727 ********************************************************************/
728
729 gid_t nametogid(const char *name)
730 {
731         struct group *grp;
732         char *p;
733         gid_t g;
734
735         g = (gid_t)strtol(name, &p, 0);
736         if ((p != name) && (*p == '\0'))
737                 return g;
738
739         grp = sys_getgrnam(name);
740         if (grp)
741                 return(grp->gr_gid);
742         return (gid_t)-1;
743 }
744
745 /*******************************************************************
746  Something really nasty happened - panic !
747 ********************************************************************/
748
749 void smb_panic_s3(const char *why)
750 {
751         char *cmd;
752         int result;
753
754         DEBUG(0,("PANIC (pid %llu): %s\n",
755                     (unsigned long long)sys_getpid(), why));
756         log_stack_trace();
757
758 #if defined(HAVE_PRCTL) && defined(PR_SET_PTRACER)
759         /*
760          * Make sure all children can attach a debugger.
761          */
762         prctl(PR_SET_PTRACER, getpid(), 0, 0, 0);
763 #endif
764
765         cmd = lp_panic_action();
766         if (cmd && *cmd) {
767                 DEBUG(0, ("smb_panic(): calling panic action [%s]\n", cmd));
768                 result = system(cmd);
769
770                 if (result == -1)
771                         DEBUG(0, ("smb_panic(): fork failed in panic action: %s\n",
772                                           strerror(errno)));
773                 else
774                         DEBUG(0, ("smb_panic(): action returned status %d\n",
775                                           WEXITSTATUS(result)));
776         }
777
778         dump_core();
779 }
780
781 /*******************************************************************
782  Print a backtrace of the stack to the debug log. This function
783  DELIBERATELY LEAKS MEMORY. The expectation is that you should
784  exit shortly after calling it.
785 ********************************************************************/
786
787 #ifdef HAVE_LIBUNWIND_H
788 #include <libunwind.h>
789 #endif
790
791 #ifdef HAVE_EXECINFO_H
792 #include <execinfo.h>
793 #endif
794
795 #ifdef HAVE_LIBEXC_H
796 #include <libexc.h>
797 #endif
798
799 void log_stack_trace(void)
800 {
801 #ifdef HAVE_LIBUNWIND
802         /* Try to use libunwind before any other technique since on ia64
803          * libunwind correctly walks the stack in more circumstances than
804          * backtrace.
805          */ 
806         unw_cursor_t cursor;
807         unw_context_t uc;
808         unsigned i = 0;
809
810         char procname[256];
811         unw_word_t ip, sp, off;
812
813         procname[sizeof(procname) - 1] = '\0';
814
815         if (unw_getcontext(&uc) != 0) {
816                 goto libunwind_failed;
817         }
818
819         if (unw_init_local(&cursor, &uc) != 0) {
820                 goto libunwind_failed;
821         }
822
823         DEBUG(0, ("BACKTRACE:\n"));
824
825         do {
826             ip = sp = 0;
827             unw_get_reg(&cursor, UNW_REG_IP, &ip);
828             unw_get_reg(&cursor, UNW_REG_SP, &sp);
829
830             switch (unw_get_proc_name(&cursor,
831                         procname, sizeof(procname) - 1, &off) ) {
832             case 0:
833                     /* Name found. */
834             case -UNW_ENOMEM:
835                     /* Name truncated. */
836                     DEBUGADD(0, (" #%u %s + %#llx [ip=%#llx] [sp=%#llx]\n",
837                             i, procname, (long long)off,
838                             (long long)ip, (long long) sp));
839                     break;
840             default:
841             /* case -UNW_ENOINFO: */
842             /* case -UNW_EUNSPEC: */
843                     /* No symbol name found. */
844                     DEBUGADD(0, (" #%u %s [ip=%#llx] [sp=%#llx]\n",
845                             i, "<unknown symbol>",
846                             (long long)ip, (long long) sp));
847             }
848             ++i;
849         } while (unw_step(&cursor) > 0);
850
851         return;
852
853 libunwind_failed:
854         DEBUG(0, ("unable to produce a stack trace with libunwind\n"));
855
856 #elif HAVE_BACKTRACE_SYMBOLS
857         void *backtrace_stack[BACKTRACE_STACK_SIZE];
858         size_t backtrace_size;
859         char **backtrace_strings;
860
861         /* get the backtrace (stack frames) */
862         backtrace_size = backtrace(backtrace_stack,BACKTRACE_STACK_SIZE);
863         backtrace_strings = backtrace_symbols(backtrace_stack, backtrace_size);
864
865         DEBUG(0, ("BACKTRACE: %lu stack frames:\n", 
866                   (unsigned long)backtrace_size));
867
868         if (backtrace_strings) {
869                 int i;
870
871                 for (i = 0; i < backtrace_size; i++)
872                         DEBUGADD(0, (" #%u %s\n", i, backtrace_strings[i]));
873
874                 /* Leak the backtrace_strings, rather than risk what free() might do */
875         }
876
877 #elif HAVE_LIBEXC
878
879         /* The IRIX libexc library provides an API for unwinding the stack. See
880          * libexc(3) for details. Apparantly trace_back_stack leaks memory, but
881          * since we are about to abort anyway, it hardly matters.
882          */
883
884 #define NAMESIZE 32 /* Arbitrary */
885
886         __uint64_t      addrs[BACKTRACE_STACK_SIZE];
887         char *          names[BACKTRACE_STACK_SIZE];
888         char            namebuf[BACKTRACE_STACK_SIZE * NAMESIZE];
889
890         int             i;
891         int             levels;
892
893         ZERO_ARRAY(addrs);
894         ZERO_ARRAY(names);
895         ZERO_ARRAY(namebuf);
896
897         /* We need to be root so we can open our /proc entry to walk
898          * our stack. It also helps when we want to dump core.
899          */
900         become_root();
901
902         for (i = 0; i < BACKTRACE_STACK_SIZE; i++) {
903                 names[i] = namebuf + (i * NAMESIZE);
904         }
905
906         levels = trace_back_stack(0, addrs, names,
907                         BACKTRACE_STACK_SIZE, NAMESIZE - 1);
908
909         DEBUG(0, ("BACKTRACE: %d stack frames:\n", levels));
910         for (i = 0; i < levels; i++) {
911                 DEBUGADD(0, (" #%d 0x%llx %s\n", i, addrs[i], names[i]));
912         }
913 #undef NAMESIZE
914
915 #else
916         DEBUG(0, ("unable to produce a stack trace on this platform\n"));
917 #endif
918 }
919
920 /*******************************************************************
921   A readdir wrapper which just returns the file name.
922  ********************************************************************/
923
924 const char *readdirname(SMB_STRUCT_DIR *p)
925 {
926         SMB_STRUCT_DIRENT *ptr;
927         char *dname;
928
929         if (!p)
930                 return(NULL);
931
932         ptr = (SMB_STRUCT_DIRENT *)sys_readdir(p);
933         if (!ptr)
934                 return(NULL);
935
936         dname = ptr->d_name;
937
938 #ifdef NEXT2
939         if (telldir(p) < 0)
940                 return(NULL);
941 #endif
942
943 #ifdef HAVE_BROKEN_READDIR_NAME
944         /* using /usr/ucb/cc is BAD */
945         dname = dname - 2;
946 #endif
947
948         return talloc_strdup(talloc_tos(), dname);
949 }
950
951 /*******************************************************************
952  Utility function used to decide if the last component 
953  of a path matches a (possibly wildcarded) entry in a namelist.
954 ********************************************************************/
955
956 bool is_in_path(const char *name, name_compare_entry *namelist, bool case_sensitive)
957 {
958         const char *last_component;
959
960         /* if we have no list it's obviously not in the path */
961         if((namelist == NULL ) || ((namelist != NULL) && (namelist[0].name == NULL))) {
962                 return False;
963         }
964
965         DEBUG(8, ("is_in_path: %s\n", name));
966
967         /* Get the last component of the unix name. */
968         last_component = strrchr_m(name, '/');
969         if (!last_component) {
970                 last_component = name;
971         } else {
972                 last_component++; /* Go past '/' */
973         }
974
975         for(; namelist->name != NULL; namelist++) {
976                 if(namelist->is_wild) {
977                         if (mask_match(last_component, namelist->name, case_sensitive)) {
978                                 DEBUG(8,("is_in_path: mask match succeeded\n"));
979                                 return True;
980                         }
981                 } else {
982                         if((case_sensitive && (strcmp(last_component, namelist->name) == 0))||
983                                                 (!case_sensitive && (strcasecmp_m(last_component, namelist->name) == 0))) {
984                                 DEBUG(8,("is_in_path: match succeeded\n"));
985                                 return True;
986                         }
987                 }
988         }
989         DEBUG(8,("is_in_path: match not found\n"));
990         return False;
991 }
992
993 /*******************************************************************
994  Strip a '/' separated list into an array of 
995  name_compare_enties structures suitable for 
996  passing to is_in_path(). We do this for
997  speed so we can pre-parse all the names in the list 
998  and don't do it for each call to is_in_path().
999  We also check if the entry contains a wildcard to
1000  remove a potentially expensive call to mask_match
1001  if possible.
1002 ********************************************************************/
1003
1004 void set_namearray(name_compare_entry **ppname_array, const char *namelist_in)
1005 {
1006         char *name_end;
1007         char *namelist;
1008         char *nameptr;
1009         int num_entries = 0;
1010         int i;
1011
1012         (*ppname_array) = NULL;
1013
1014         if((namelist_in == NULL ) || ((namelist_in != NULL) && (*namelist_in == '\0'))) 
1015                 return;
1016
1017         namelist = talloc_strdup(talloc_tos(), namelist_in);
1018         if (namelist == NULL) {
1019                 DEBUG(0,("set_namearray: talloc fail\n"));
1020                 return;
1021         }
1022         nameptr = namelist;
1023
1024         /* We need to make two passes over the string. The
1025                 first to count the number of elements, the second
1026                 to split it.
1027         */
1028
1029         while(*nameptr) {
1030                 if ( *nameptr == '/' ) {
1031                         /* cope with multiple (useless) /s) */
1032                         nameptr++;
1033                         continue;
1034                 }
1035                 /* anything left? */
1036                 if ( *nameptr == '\0' )
1037                         break;
1038
1039                 /* find the next '/' or consume remaining */
1040                 name_end = strchr_m(nameptr, '/');
1041                 if (name_end == NULL)
1042                         name_end = (char *)nameptr + strlen(nameptr);
1043
1044                 /* next segment please */
1045                 nameptr = name_end + 1;
1046                 num_entries++;
1047         }
1048
1049         if(num_entries == 0) {
1050                 talloc_free(namelist);
1051                 return;
1052         }
1053
1054         if(( (*ppname_array) = SMB_MALLOC_ARRAY(name_compare_entry, num_entries + 1)) == NULL) {
1055                 DEBUG(0,("set_namearray: malloc fail\n"));
1056                 talloc_free(namelist);
1057                 return;
1058         }
1059
1060         /* Now copy out the names */
1061         nameptr = namelist;
1062         i = 0;
1063         while(*nameptr) {
1064                 if ( *nameptr == '/' ) {
1065                         /* cope with multiple (useless) /s) */
1066                         nameptr++;
1067                         continue;
1068                 }
1069                 /* anything left? */
1070                 if ( *nameptr == '\0' )
1071                         break;
1072
1073                 /* find the next '/' or consume remaining */
1074                 name_end = strchr_m(nameptr, '/');
1075                 if (name_end)
1076                         *name_end = '\0';
1077                 else
1078                         name_end = nameptr + strlen(nameptr);
1079
1080                 (*ppname_array)[i].is_wild = ms_has_wild(nameptr);
1081                 if(((*ppname_array)[i].name = SMB_STRDUP(nameptr)) == NULL) {
1082                         DEBUG(0,("set_namearray: malloc fail (1)\n"));
1083                         talloc_free(namelist);
1084                         return;
1085                 }
1086
1087                 /* next segment please */
1088                 nameptr = name_end + 1;
1089                 i++;
1090         }
1091
1092         (*ppname_array)[i].name = NULL;
1093
1094         talloc_free(namelist);
1095         return;
1096 }
1097
1098 #undef DBGC_CLASS
1099 #define DBGC_CLASS DBGC_LOCKING
1100
1101 /****************************************************************************
1102  Simple routine to query existing file locks. Cruft in NFS and 64->32 bit mapping
1103  is dealt with in posix.c
1104  Returns True if we have information regarding this lock region (and returns
1105  F_UNLCK in *ptype if the region is unlocked). False if the call failed.
1106 ****************************************************************************/
1107
1108 bool fcntl_getlock(int fd, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype, pid_t *ppid)
1109 {
1110         SMB_STRUCT_FLOCK lock;
1111         int ret;
1112
1113         DEBUG(8,("fcntl_getlock fd=%d offset=%.0f count=%.0f type=%d\n",
1114                     fd,(double)*poffset,(double)*pcount,*ptype));
1115
1116         lock.l_type = *ptype;
1117         lock.l_whence = SEEK_SET;
1118         lock.l_start = *poffset;
1119         lock.l_len = *pcount;
1120         lock.l_pid = 0;
1121
1122         ret = sys_fcntl_ptr(fd,SMB_F_GETLK,&lock);
1123
1124         if (ret == -1) {
1125                 int sav = errno;
1126                 DEBUG(3,("fcntl_getlock: lock request failed at offset %.0f count %.0f type %d (%s)\n",
1127                         (double)*poffset,(double)*pcount,*ptype,strerror(errno)));
1128                 errno = sav;
1129                 return False;
1130         }
1131
1132         *ptype = lock.l_type;
1133         *poffset = lock.l_start;
1134         *pcount = lock.l_len;
1135         *ppid = lock.l_pid;
1136
1137         DEBUG(3,("fcntl_getlock: fd %d is returned info %d pid %u\n",
1138                         fd, (int)lock.l_type, (unsigned int)lock.l_pid));
1139         return True;
1140 }
1141
1142 #undef DBGC_CLASS
1143 #define DBGC_CLASS DBGC_ALL
1144
1145 /*******************************************************************
1146  Is the name specified one of my netbios names.
1147  Returns true if it is equal, false otherwise.
1148 ********************************************************************/
1149
1150 bool is_myname(const char *s)
1151 {
1152         int n;
1153         bool ret = False;
1154
1155         for (n=0; my_netbios_names(n); n++) {
1156                 if (strequal(my_netbios_names(n), s)) {
1157                         ret=True;
1158                         break;
1159                 }
1160         }
1161         DEBUG(8, ("is_myname(\"%s\") returns %d\n", s, ret));
1162         return(ret);
1163 }
1164
1165 /*******************************************************************
1166  Is the name specified our workgroup/domain.
1167  Returns true if it is equal, false otherwise.
1168 ********************************************************************/
1169
1170 bool is_myworkgroup(const char *s)
1171 {
1172         bool ret = False;
1173
1174         if (strequal(s, lp_workgroup())) {
1175                 ret=True;
1176         }
1177
1178         DEBUG(8, ("is_myworkgroup(\"%s\") returns %d\n", s, ret));
1179         return(ret);
1180 }
1181
1182 /*******************************************************************
1183  we distinguish between 2K and XP by the "Native Lan Manager" string
1184    WinXP => "Windows 2002 5.1"
1185    WinXP 64bit => "Windows XP 5.2"
1186    Win2k => "Windows 2000 5.0"
1187    NT4   => "Windows NT 4.0"
1188    Win9x => "Windows 4.0"
1189  Windows 2003 doesn't set the native lan manager string but
1190  they do set the domain to "Windows 2003 5.2" (probably a bug).
1191 ********************************************************************/
1192
1193 void ra_lanman_string( const char *native_lanman )
1194 {
1195         if ( strcmp( native_lanman, "Windows 2002 5.1" ) == 0 )
1196                 set_remote_arch( RA_WINXP );
1197         else if ( strcmp( native_lanman, "Windows XP 5.2" ) == 0 )
1198                 set_remote_arch( RA_WINXP64 );
1199         else if ( strcmp( native_lanman, "Windows Server 2003 5.2" ) == 0 )
1200                 set_remote_arch( RA_WIN2K3 );
1201 }
1202
1203 static const char *remote_arch_str;
1204
1205 const char *get_remote_arch_str(void)
1206 {
1207         if (!remote_arch_str) {
1208                 return "UNKNOWN";
1209         }
1210         return remote_arch_str;
1211 }
1212
1213 /*******************************************************************
1214  Set the horrid remote_arch string based on an enum.
1215 ********************************************************************/
1216
1217 void set_remote_arch(enum remote_arch_types type)
1218 {
1219         ra_type = type;
1220         switch( type ) {
1221         case RA_WFWG:
1222                 remote_arch_str = "WfWg";
1223                 break;
1224         case RA_OS2:
1225                 remote_arch_str = "OS2";
1226                 break;
1227         case RA_WIN95:
1228                 remote_arch_str = "Win95";
1229                 break;
1230         case RA_WINNT:
1231                 remote_arch_str = "WinNT";
1232                 break;
1233         case RA_WIN2K:
1234                 remote_arch_str = "Win2K";
1235                 break;
1236         case RA_WINXP:
1237                 remote_arch_str = "WinXP";
1238                 break;
1239         case RA_WINXP64:
1240                 remote_arch_str = "WinXP64";
1241                 break;
1242         case RA_WIN2K3:
1243                 remote_arch_str = "Win2K3";
1244                 break;
1245         case RA_VISTA:
1246                 remote_arch_str = "Vista";
1247                 break;
1248         case RA_SAMBA:
1249                 remote_arch_str = "Samba";
1250                 break;
1251         case RA_CIFSFS:
1252                 remote_arch_str = "CIFSFS";
1253                 break;
1254         case RA_OSX:
1255                 remote_arch_str = "OSX";
1256                 break;
1257         default:
1258                 ra_type = RA_UNKNOWN;
1259                 remote_arch_str = "UNKNOWN";
1260                 break;
1261         }
1262
1263         DEBUG(10,("set_remote_arch: Client arch is \'%s\'\n",
1264                                 remote_arch_str));
1265 }
1266
1267 /*******************************************************************
1268  Get the remote_arch type.
1269 ********************************************************************/
1270
1271 enum remote_arch_types get_remote_arch(void)
1272 {
1273         return ra_type;
1274 }
1275
1276 const char *tab_depth(int level, int depth)
1277 {
1278         if( CHECK_DEBUGLVL(level) ) {
1279                 dbgtext("%*s", depth*4, "");
1280         }
1281         return "";
1282 }
1283
1284 /*****************************************************************************
1285  Provide a checksum on a string
1286
1287  Input:  s - the null-terminated character string for which the checksum
1288              will be calculated.
1289
1290   Output: The checksum value calculated for s.
1291 *****************************************************************************/
1292
1293 int str_checksum(const char *s)
1294 {
1295         if (s == NULL)
1296                 return 0;
1297         return hash(s, strlen(s), 0);
1298 }
1299
1300 /*****************************************************************
1301  Zero a memory area then free it. Used to catch bugs faster.
1302 *****************************************************************/  
1303
1304 void zero_free(void *p, size_t size)
1305 {
1306         memset(p, 0, size);
1307         SAFE_FREE(p);
1308 }
1309
1310 /*****************************************************************
1311  Set our open file limit to a requested max and return the limit.
1312 *****************************************************************/  
1313
1314 int set_maxfiles(int requested_max)
1315 {
1316 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
1317         struct rlimit rlp;
1318         int saved_current_limit;
1319
1320         if(getrlimit(RLIMIT_NOFILE, &rlp)) {
1321                 DEBUG(0,("set_maxfiles: getrlimit (1) for RLIMIT_NOFILE failed with error %s\n",
1322                         strerror(errno) ));
1323                 /* just guess... */
1324                 return requested_max;
1325         }
1326
1327         /* 
1328          * Set the fd limit to be real_max_open_files + MAX_OPEN_FUDGEFACTOR to
1329          * account for the extra fd we need 
1330          * as well as the log files and standard
1331          * handles etc. Save the limit we want to set in case
1332          * we are running on an OS that doesn't support this limit (AIX)
1333          * which always returns RLIM_INFINITY for rlp.rlim_max.
1334          */
1335
1336         /* Try raising the hard (max) limit to the requested amount. */
1337
1338 #if defined(RLIM_INFINITY)
1339         if (rlp.rlim_max != RLIM_INFINITY) {
1340                 int orig_max = rlp.rlim_max;
1341
1342                 if ( rlp.rlim_max < requested_max )
1343                         rlp.rlim_max = requested_max;
1344
1345                 /* This failing is not an error - many systems (Linux) don't
1346                         support our default request of 10,000 open files. JRA. */
1347
1348                 if(setrlimit(RLIMIT_NOFILE, &rlp)) {
1349                         DEBUG(3,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d max files failed with error %s\n", 
1350                                 (int)rlp.rlim_max, strerror(errno) ));
1351
1352                         /* Set failed - restore original value from get. */
1353                         rlp.rlim_max = orig_max;
1354                 }
1355         }
1356 #endif
1357
1358         /* Now try setting the soft (current) limit. */
1359
1360         saved_current_limit = rlp.rlim_cur = MIN(requested_max,rlp.rlim_max);
1361
1362         if(setrlimit(RLIMIT_NOFILE, &rlp)) {
1363                 DEBUG(0,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d files failed with error %s\n", 
1364                         (int)rlp.rlim_cur, strerror(errno) ));
1365                 /* just guess... */
1366                 return saved_current_limit;
1367         }
1368
1369         if(getrlimit(RLIMIT_NOFILE, &rlp)) {
1370                 DEBUG(0,("set_maxfiles: getrlimit (2) for RLIMIT_NOFILE failed with error %s\n",
1371                         strerror(errno) ));
1372                 /* just guess... */
1373                 return saved_current_limit;
1374     }
1375
1376 #if defined(RLIM_INFINITY)
1377         if(rlp.rlim_cur == RLIM_INFINITY)
1378                 return saved_current_limit;
1379 #endif
1380
1381         if((int)rlp.rlim_cur > saved_current_limit)
1382                 return saved_current_limit;
1383
1384         return rlp.rlim_cur;
1385 #else /* !defined(HAVE_GETRLIMIT) || !defined(RLIMIT_NOFILE) */
1386         /*
1387          * No way to know - just guess...
1388          */
1389         return requested_max;
1390 #endif
1391 }
1392
1393 /*****************************************************************
1394  malloc that aborts with smb_panic on fail or zero size.
1395  *****************************************************************/  
1396
1397 void *smb_xmalloc_array(size_t size, unsigned int count)
1398 {
1399         void *p;
1400         if (size == 0) {
1401                 smb_panic("smb_xmalloc_array: called with zero size");
1402         }
1403         if (count >= MAX_ALLOC_SIZE/size) {
1404                 smb_panic("smb_xmalloc_array: alloc size too large");
1405         }
1406         if ((p = SMB_MALLOC(size*count)) == NULL) {
1407                 DEBUG(0, ("smb_xmalloc_array failed to allocate %lu * %lu bytes\n",
1408                         (unsigned long)size, (unsigned long)count));
1409                 smb_panic("smb_xmalloc_array: malloc failed");
1410         }
1411         return p;
1412 }
1413
1414 /*
1415   vasprintf that aborts on malloc fail
1416 */
1417
1418  int smb_xvasprintf(char **ptr, const char *format, va_list ap)
1419 {
1420         int n;
1421         va_list ap2;
1422
1423         va_copy(ap2, ap);
1424
1425         n = vasprintf(ptr, format, ap2);
1426         va_end(ap2);
1427         if (n == -1 || ! *ptr) {
1428                 smb_panic("smb_xvasprintf: out of memory");
1429         }
1430         return n;
1431 }
1432
1433 /*****************************************************************
1434  Get local hostname and cache result.
1435 *****************************************************************/
1436
1437 char *myhostname(void)
1438 {
1439         static char *ret;
1440         if (ret == NULL) {
1441                 ret = get_myname(NULL);
1442         }
1443         return ret;
1444 }
1445
1446 /*****************************************************************
1447  Get local hostname and cache result.
1448 *****************************************************************/
1449
1450 char *myhostname_upper(void)
1451 {
1452         char *name;
1453         static char *ret;
1454         if (ret == NULL) {
1455                 name = get_myname(talloc_tos());
1456                 ret = strupper_talloc(NULL, name);
1457                 talloc_free(name);
1458         }
1459         return ret;
1460 }
1461
1462 /**
1463  * @brief Returns an absolute path to a file concatenating the provided
1464  * @a rootpath and @a basename
1465  *
1466  * @param name Filename, relative to @a rootpath
1467  *
1468  * @retval Pointer to a string containing the full path.
1469  **/
1470
1471 static char *xx_path(const char *name, const char *rootpath)
1472 {
1473         char *fname = NULL;
1474
1475         fname = talloc_strdup(talloc_tos(), rootpath);
1476         if (!fname) {
1477                 return NULL;
1478         }
1479         trim_string(fname,"","/");
1480
1481         if (!directory_exist(fname)) {
1482                 if (!mkdir(fname,0755))
1483                         DEBUG(1, ("Unable to create directory %s for file %s. "
1484                               "Error was %s\n", fname, name, strerror(errno)));
1485         }
1486
1487         return talloc_asprintf(talloc_tos(),
1488                                 "%s/%s",
1489                                 fname,
1490                                 name);
1491 }
1492
1493 /**
1494  * @brief Returns an absolute path to a file in the Samba lock directory.
1495  *
1496  * @param name File to find, relative to LOCKDIR.
1497  *
1498  * @retval Pointer to a talloc'ed string containing the full path.
1499  **/
1500
1501 char *lock_path(const char *name)
1502 {
1503         return xx_path(name, lp_lockdir());
1504 }
1505
1506 /**
1507  * @brief Returns an absolute path to a file in the Samba pid directory.
1508  *
1509  * @param name File to find, relative to PIDDIR.
1510  *
1511  * @retval Pointer to a talloc'ed string containing the full path.
1512  **/
1513
1514 char *pid_path(const char *name)
1515 {
1516         return xx_path(name, lp_piddir());
1517 }
1518
1519 /**
1520  * @brief Returns an absolute path to a file in the Samba state directory.
1521  *
1522  * @param name File to find, relative to STATEDIR.
1523  *
1524  * @retval Pointer to a talloc'ed string containing the full path.
1525  **/
1526
1527 char *state_path(const char *name)
1528 {
1529         return xx_path(name, lp_statedir());
1530 }
1531
1532 /**
1533  * @brief Returns an absolute path to a file in the Samba cache directory.
1534  *
1535  * @param name File to find, relative to CACHEDIR.
1536  *
1537  * @retval Pointer to a talloc'ed string containing the full path.
1538  **/
1539
1540 char *cache_path(const char *name)
1541 {
1542         return xx_path(name, lp_cachedir());
1543 }
1544
1545 /*******************************************************************
1546  Given a filename - get its directory name
1547 ********************************************************************/
1548
1549 bool parent_dirname(TALLOC_CTX *mem_ctx, const char *dir, char **parent,
1550                     const char **name)
1551 {
1552         char *p;
1553         ptrdiff_t len;
1554
1555         p = strrchr_m(dir, '/'); /* Find final '/', if any */
1556
1557         if (p == NULL) {
1558                 if (!(*parent = talloc_strdup(mem_ctx, "."))) {
1559                         return False;
1560                 }
1561                 if (name) {
1562                         *name = dir;
1563                 }
1564                 return True;
1565         }
1566
1567         len = p-dir;
1568
1569         if (!(*parent = (char *)talloc_memdup(mem_ctx, dir, len+1))) {
1570                 return False;
1571         }
1572         (*parent)[len] = '\0';
1573
1574         if (name) {
1575                 *name = p+1;
1576         }
1577         return True;
1578 }
1579
1580 /*******************************************************************
1581  Determine if a pattern contains any Microsoft wildcard characters.
1582 *******************************************************************/
1583
1584 bool ms_has_wild(const char *s)
1585 {
1586         char c;
1587
1588         if (lp_posix_pathnames()) {
1589                 /* With posix pathnames no characters are wild. */
1590                 return False;
1591         }
1592
1593         while ((c = *s++)) {
1594                 switch (c) {
1595                 case '*':
1596                 case '?':
1597                 case '<':
1598                 case '>':
1599                 case '"':
1600                         return True;
1601                 }
1602         }
1603         return False;
1604 }
1605
1606 bool ms_has_wild_w(const smb_ucs2_t *s)
1607 {
1608         smb_ucs2_t c;
1609         if (!s) return False;
1610         while ((c = *s++)) {
1611                 switch (c) {
1612                 case UCS2_CHAR('*'):
1613                 case UCS2_CHAR('?'):
1614                 case UCS2_CHAR('<'):
1615                 case UCS2_CHAR('>'):
1616                 case UCS2_CHAR('"'):
1617                         return True;
1618                 }
1619         }
1620         return False;
1621 }
1622
1623 /*******************************************************************
1624  A wrapper that handles case sensitivity and the special handling
1625  of the ".." name.
1626 *******************************************************************/
1627
1628 bool mask_match(const char *string, const char *pattern, bool is_case_sensitive)
1629 {
1630         if (ISDOTDOT(string))
1631                 string = ".";
1632         if (ISDOT(pattern))
1633                 return False;
1634
1635         return ms_fnmatch(pattern, string, Protocol <= PROTOCOL_LANMAN2, is_case_sensitive) == 0;
1636 }
1637
1638 /*******************************************************************
1639  A wrapper that handles case sensitivity and the special handling
1640  of the ".." name. Varient that is only called by old search code which requires
1641  pattern translation.
1642 *******************************************************************/
1643
1644 bool mask_match_search(const char *string, const char *pattern, bool is_case_sensitive)
1645 {
1646         if (ISDOTDOT(string))
1647                 string = ".";
1648         if (ISDOT(pattern))
1649                 return False;
1650
1651         return ms_fnmatch(pattern, string, True, is_case_sensitive) == 0;
1652 }
1653
1654 /*******************************************************************
1655  A wrapper that handles a list of patters and calls mask_match()
1656  on each.  Returns True if any of the patterns match.
1657 *******************************************************************/
1658
1659 bool mask_match_list(const char *string, char **list, int listLen, bool is_case_sensitive)
1660 {
1661        while (listLen-- > 0) {
1662                if (mask_match(string, *list++, is_case_sensitive))
1663                        return True;
1664        }
1665        return False;
1666 }
1667
1668 /*********************************************************
1669  Recursive routine that is called by unix_wild_match.
1670 *********************************************************/
1671
1672 static bool unix_do_match(const char *regexp, const char *str)
1673 {
1674         const char *p;
1675
1676         for( p = regexp; *p && *str; ) {
1677
1678                 switch(*p) {
1679                         case '?':
1680                                 str++;
1681                                 p++;
1682                                 break;
1683
1684                         case '*':
1685
1686                                 /*
1687                                  * Look for a character matching 
1688                                  * the one after the '*'.
1689                                  */
1690                                 p++;
1691                                 if(!*p)
1692                                         return true; /* Automatic match */
1693                                 while(*str) {
1694
1695                                         while(*str && (*p != *str))
1696                                                 str++;
1697
1698                                         /*
1699                                          * Patch from weidel@multichart.de. In the case of the regexp
1700                                          * '*XX*' we want to ensure there are at least 2 'X' characters
1701                                          * in the string after the '*' for a match to be made.
1702                                          */
1703
1704                                         {
1705                                                 int matchcount=0;
1706
1707                                                 /*
1708                                                  * Eat all the characters that match, but count how many there were.
1709                                                  */
1710
1711                                                 while(*str && (*p == *str)) {
1712                                                         str++;
1713                                                         matchcount++;
1714                                                 }
1715
1716                                                 /*
1717                                                  * Now check that if the regexp had n identical characters that
1718                                                  * matchcount had at least that many matches.
1719                                                  */
1720
1721                                                 while ( *(p+1) && (*(p+1) == *p)) {
1722                                                         p++;
1723                                                         matchcount--;
1724                                                 }
1725
1726                                                 if ( matchcount <= 0 )
1727                                                         return false;
1728                                         }
1729
1730                                         str--; /* We've eaten the match char after the '*' */
1731
1732                                         if(unix_do_match(p, str))
1733                                                 return true;
1734
1735                                         if(!*str)
1736                                                 return false;
1737                                         else
1738                                                 str++;
1739                                 }
1740                                 return false;
1741
1742                         default:
1743                                 if(*str != *p)
1744                                         return false;
1745                                 str++;
1746                                 p++;
1747                                 break;
1748                 }
1749         }
1750
1751         if(!*p && !*str)
1752                 return true;
1753
1754         if (!*p && str[0] == '.' && str[1] == 0)
1755                 return true;
1756
1757         if (!*str && *p == '?') {
1758                 while (*p == '?')
1759                         p++;
1760                 return(!*p);
1761         }
1762
1763         if(!*str && (*p == '*' && p[1] == '\0'))
1764                 return true;
1765
1766         return false;
1767 }
1768
1769 /*******************************************************************
1770  Simple case insensitive interface to a UNIX wildcard matcher.
1771  Returns True if match, False if not.
1772 *******************************************************************/
1773
1774 bool unix_wild_match(const char *pattern, const char *string)
1775 {
1776         TALLOC_CTX *ctx = talloc_stackframe();
1777         char *p2;
1778         char *s2;
1779         char *p;
1780         bool ret = false;
1781
1782         p2 = talloc_strdup(ctx,pattern);
1783         s2 = talloc_strdup(ctx,string);
1784         if (!p2 || !s2) {
1785                 TALLOC_FREE(ctx);
1786                 return false;
1787         }
1788         strlower_m(p2);
1789         strlower_m(s2);
1790
1791         /* Remove any *? and ** from the pattern as they are meaningless */
1792         for(p = p2; *p; p++) {
1793                 while( *p == '*' && (p[1] == '?' ||p[1] == '*')) {
1794                         memmove(&p[1], &p[2], strlen(&p[2])+1);
1795                 }
1796         }
1797
1798         if (strequal(p2,"*")) {
1799                 TALLOC_FREE(ctx);
1800                 return true;
1801         }
1802
1803         ret = unix_do_match(p2, s2);
1804         TALLOC_FREE(ctx);
1805         return ret;
1806 }
1807
1808 /**********************************************************************
1809  Converts a name to a fully qualified domain name.
1810  Returns true if lookup succeeded, false if not (then fqdn is set to name)
1811  Note we deliberately use gethostbyname here, not getaddrinfo as we want
1812  to examine the h_aliases and I don't know how to do that with getaddrinfo.
1813 ***********************************************************************/
1814
1815 bool name_to_fqdn(fstring fqdn, const char *name)
1816 {
1817         char *full = NULL;
1818         struct hostent *hp = gethostbyname(name);
1819
1820         if (!hp || !hp->h_name || !*hp->h_name) {
1821                 DEBUG(10,("name_to_fqdn: lookup for %s failed.\n", name));
1822                 fstrcpy(fqdn, name);
1823                 return false;
1824         }
1825
1826         /* Find out if the fqdn is returned as an alias
1827          * to cope with /etc/hosts files where the first
1828          * name is not the fqdn but the short name */
1829         if (hp->h_aliases && (! strchr_m(hp->h_name, '.'))) {
1830                 int i;
1831                 for (i = 0; hp->h_aliases[i]; i++) {
1832                         if (strchr_m(hp->h_aliases[i], '.')) {
1833                                 full = hp->h_aliases[i];
1834                                 break;
1835                         }
1836                 }
1837         }
1838         if (full && (strcasecmp_m(full, "localhost.localdomain") == 0)) {
1839                 DEBUG(1, ("WARNING: your /etc/hosts file may be broken!\n"));
1840                 DEBUGADD(1, ("    Specifing the machine hostname for address 127.0.0.1 may lead\n"));
1841                 DEBUGADD(1, ("    to Kerberos authentication problems as localhost.localdomain\n"));
1842                 DEBUGADD(1, ("    may end up being used instead of the real machine FQDN.\n"));
1843                 full = hp->h_name;
1844         }
1845         if (!full) {
1846                 full = hp->h_name;
1847         }
1848
1849         DEBUG(10,("name_to_fqdn: lookup for %s -> %s.\n", name, full));
1850         fstrcpy(fqdn, full);
1851         return true;
1852 }
1853
1854 /**********************************************************************
1855  Append a DATA_BLOB to a talloc'ed object
1856 ***********************************************************************/
1857
1858 void *talloc_append_blob(TALLOC_CTX *mem_ctx, void *buf, DATA_BLOB blob)
1859 {
1860         size_t old_size = 0;
1861         char *result;
1862
1863         if (blob.length == 0) {
1864                 return buf;
1865         }
1866
1867         if (buf != NULL) {
1868                 old_size = talloc_get_size(buf);
1869         }
1870
1871         result = (char *)TALLOC_REALLOC(mem_ctx, buf, old_size + blob.length);
1872         if (result == NULL) {
1873                 return NULL;
1874         }
1875
1876         memcpy(result + old_size, blob.data, blob.length);
1877         return result;
1878 }
1879
1880 uint32 map_share_mode_to_deny_mode(uint32 share_access, uint32 private_options)
1881 {
1882         switch (share_access & ~FILE_SHARE_DELETE) {
1883                 case FILE_SHARE_NONE:
1884                         return DENY_ALL;
1885                 case FILE_SHARE_READ:
1886                         return DENY_WRITE;
1887                 case FILE_SHARE_WRITE:
1888                         return DENY_READ;
1889                 case FILE_SHARE_READ|FILE_SHARE_WRITE:
1890                         return DENY_NONE;
1891         }
1892         if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS) {
1893                 return DENY_DOS;
1894         } else if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_FCB) {
1895                 return DENY_FCB;
1896         }
1897
1898         return (uint32)-1;
1899 }
1900
1901 pid_t procid_to_pid(const struct server_id *proc)
1902 {
1903         return proc->pid;
1904 }
1905
1906 static uint32 my_vnn = NONCLUSTER_VNN;
1907
1908 void set_my_vnn(uint32 vnn)
1909 {
1910         DEBUG(10, ("vnn pid %d = %u\n", (int)sys_getpid(), (unsigned int)vnn));
1911         my_vnn = vnn;
1912 }
1913
1914 uint32 get_my_vnn(void)
1915 {
1916         return my_vnn;
1917 }
1918
1919 static uint64_t my_unique_id = 0;
1920
1921 void set_my_unique_id(uint64_t unique_id)
1922 {
1923         my_unique_id = unique_id;
1924 }
1925
1926 struct server_id pid_to_procid(pid_t pid)
1927 {
1928         struct server_id result;
1929         result.pid = pid;
1930         result.task_id = 0;
1931         result.unique_id = my_unique_id;
1932         result.vnn = my_vnn;
1933         return result;
1934 }
1935
1936 struct server_id procid_self(void)
1937 {
1938         return pid_to_procid(sys_getpid());
1939 }
1940
1941 bool procid_equal(const struct server_id *p1, const struct server_id *p2)
1942 {
1943         if (p1->pid != p2->pid)
1944                 return False;
1945         if (p1->task_id != p2->task_id)
1946                 return False;
1947         if (p1->vnn != p2->vnn)
1948                 return False;
1949         return True;
1950 }
1951
1952 bool cluster_id_equal(const struct server_id *id1,
1953                       const struct server_id *id2)
1954 {
1955         return procid_equal(id1, id2);
1956 }
1957
1958 bool procid_is_me(const struct server_id *pid)
1959 {
1960         if (pid->pid != sys_getpid())
1961                 return False;
1962         if (pid->task_id != 0)
1963                 return False;
1964         if (pid->vnn != my_vnn)
1965                 return False;
1966         return True;
1967 }
1968
1969 struct server_id interpret_pid(const char *pid_string)
1970 {
1971         struct server_id result;
1972         unsigned long long pid;
1973         unsigned int vnn, task_id = 0;
1974
1975         ZERO_STRUCT(result);
1976
1977         /* We accept various forms with 1, 2 or 3 component forms
1978          * because the server_id_str() can print different forms, and
1979          * we want backwards compatibility for scripts that may call
1980          * smbclient. */
1981         if (sscanf(pid_string, "%u:%llu.%u", &vnn, &pid, &task_id) == 3) {
1982                 result.vnn = vnn;
1983                 result.pid = pid;
1984                 result.task_id = task_id;
1985         } else if (sscanf(pid_string, "%u:%llu", &vnn, &pid) == 2) {
1986                 result.vnn = vnn;
1987                 result.pid = pid;
1988                 result.task_id = 0;
1989         } else if (sscanf(pid_string, "%llu.%u", &pid, &task_id) == 2) {
1990                 result.vnn = get_my_vnn();
1991                 result.pid = pid;
1992                 result.task_id = task_id;
1993         } else if (sscanf(pid_string, "%llu", &pid) == 1) {
1994                 result.vnn = get_my_vnn();
1995                 result.pid = pid;
1996         } else {
1997                 result.vnn = NONCLUSTER_VNN;
1998                 result.pid = (uint64_t)-1;
1999         }
2000         return result;
2001 }
2002
2003 char *procid_str_static(const struct server_id *pid)
2004 {
2005         return server_id_str(talloc_tos(), pid);
2006 }
2007
2008 bool procid_valid(const struct server_id *pid)
2009 {
2010         return (pid->pid != (uint64_t)-1);
2011 }
2012
2013 bool procid_is_local(const struct server_id *pid)
2014 {
2015         return pid->vnn == my_vnn;
2016 }
2017
2018 /****************************************************************
2019  Check if offset/length fit into bufsize. Should probably be
2020  merged with is_offset_safe, but this would require a rewrite
2021  of lanman.c. Later :-)
2022 ****************************************************************/
2023
2024 bool trans_oob(uint32_t bufsize, uint32_t offset, uint32_t length)
2025 {
2026         if ((offset + length < offset) || (offset + length < length)) {
2027                 /* wrap */
2028                 return true;
2029         }
2030         if ((offset > bufsize) || (offset + length > bufsize)) {
2031                 /* overflow */
2032                 return true;
2033         }
2034         return false;
2035 }
2036
2037 /****************************************************************
2038  Check if an offset into a buffer is safe.
2039  If this returns True it's safe to indirect into the byte at
2040  pointer ptr+off.
2041 ****************************************************************/
2042
2043 bool is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
2044 {
2045         const char *end_base = buf_base + buf_len;
2046         char *end_ptr = ptr + off;
2047
2048         if (!buf_base || !ptr) {
2049                 return False;
2050         }
2051
2052         if (end_base < buf_base || end_ptr < ptr) {
2053                 return False; /* wrap. */
2054         }
2055
2056         if (end_ptr < end_base) {
2057                 return True;
2058         }
2059         return False;
2060 }
2061
2062 /****************************************************************
2063  Return a safe pointer into a buffer, or NULL.
2064 ****************************************************************/
2065
2066 char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
2067 {
2068         return is_offset_safe(buf_base, buf_len, ptr, off) ?
2069                         ptr + off : NULL;
2070 }
2071
2072 /****************************************************************
2073  Return a safe pointer into a string within a buffer, or NULL.
2074 ****************************************************************/
2075
2076 char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
2077 {
2078         if (!is_offset_safe(buf_base, buf_len, ptr, off)) {
2079                 return NULL;
2080         }
2081         /* Check if a valid string exists at this offset. */
2082         if (skip_string(buf_base,buf_len, ptr + off) == NULL) {
2083                 return NULL;
2084         }
2085         return ptr + off;
2086 }
2087
2088 /****************************************************************
2089  Return an SVAL at a pointer, or failval if beyond the end.
2090 ****************************************************************/
2091
2092 int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
2093 {
2094         /*
2095          * Note we use off+1 here, not off+2 as SVAL accesses ptr[0] and ptr[1],
2096          * NOT ptr[2].
2097          */
2098         if (!is_offset_safe(buf_base, buf_len, ptr, off+1)) {
2099                 return failval;
2100         }
2101         return SVAL(ptr,off);
2102 }
2103
2104 /****************************************************************
2105  Return an IVAL at a pointer, or failval if beyond the end.
2106 ****************************************************************/
2107
2108 int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
2109 {
2110         /*
2111          * Note we use off+3 here, not off+4 as IVAL accesses 
2112          * ptr[0] ptr[1] ptr[2] ptr[3] NOT ptr[4].
2113          */
2114         if (!is_offset_safe(buf_base, buf_len, ptr, off+3)) {
2115                 return failval;
2116         }
2117         return IVAL(ptr,off);
2118 }
2119
2120 /****************************************************************
2121  Split DOM\user into DOM and user. Do not mix with winbind variants of that
2122  call (they take care of winbind separator and other winbind specific settings).
2123 ****************************************************************/
2124
2125 void split_domain_user(TALLOC_CTX *mem_ctx,
2126                        const char *full_name,
2127                        char **domain,
2128                        char **user)
2129 {
2130         const char *p = NULL;
2131
2132         p = strchr_m(full_name, '\\');
2133
2134         if (p != NULL) {
2135                 *domain = talloc_strndup(mem_ctx, full_name,
2136                                          PTR_DIFF(p, full_name));
2137                 *user = talloc_strdup(mem_ctx, p+1);
2138         } else {
2139                 *domain = talloc_strdup(mem_ctx, "");
2140                 *user = talloc_strdup(mem_ctx, full_name);
2141         }
2142 }
2143
2144 /****************************************************************
2145  strip off leading '\\' from a hostname
2146 ****************************************************************/
2147
2148 const char *strip_hostname(const char *s)
2149 {
2150         if (!s) {
2151                 return NULL;
2152         }
2153
2154         if (strlen_m(s) < 3) {
2155                 return s;
2156         }
2157
2158         if (s[0] == '\\') s++;
2159         if (s[0] == '\\') s++;
2160
2161         return s;
2162 }
2163
2164 bool tevent_req_poll_ntstatus(struct tevent_req *req,
2165                               struct tevent_context *ev,
2166                               NTSTATUS *status)
2167 {
2168         bool ret = tevent_req_poll(req, ev);
2169         if (!ret) {
2170                 *status = map_nt_error_from_unix(errno);
2171         }
2172         return ret;
2173 }
2174
2175 bool any_nt_status_not_ok(NTSTATUS err1, NTSTATUS err2, NTSTATUS *result)
2176 {
2177         if (!NT_STATUS_IS_OK(err1)) {
2178                 *result = err1;
2179                 return true;
2180         }
2181         if (!NT_STATUS_IS_OK(err2)) {
2182                 *result = err2;
2183                 return true;
2184         }
2185         return false;
2186 }
2187
2188 int timeval_to_msec(struct timeval t)
2189 {
2190         return t.tv_sec * 1000 + (t.tv_usec+999) / 1000;
2191 }
2192
2193 /*******************************************************************
2194  Check a given DOS pathname is valid for a share.
2195 ********************************************************************/
2196
2197 char *valid_share_pathname(TALLOC_CTX *ctx, const char *dos_pathname)
2198 {
2199         char *ptr = NULL;
2200
2201         if (!dos_pathname) {
2202                 return NULL;
2203         }
2204
2205         ptr = talloc_strdup(ctx, dos_pathname);
2206         if (!ptr) {
2207                 return NULL;
2208         }
2209         /* Convert any '\' paths to '/' */
2210         unix_format(ptr);
2211         ptr = unix_clean_name(ctx, ptr);
2212         if (!ptr) {
2213                 return NULL;
2214         }
2215
2216         /* NT is braindead - it wants a C: prefix to a pathname ! So strip it. */
2217         if (strlen(ptr) > 2 && ptr[1] == ':' && ptr[0] != '/')
2218                 ptr += 2;
2219
2220         /* Only absolute paths allowed. */
2221         if (*ptr != '/')
2222                 return NULL;
2223
2224         return ptr;
2225 }
2226
2227 /*******************************************************************
2228  Return True if the filename is one of the special executable types.
2229 ********************************************************************/
2230
2231 bool is_executable(const char *fname)
2232 {
2233         if ((fname = strrchr_m(fname,'.'))) {
2234                 if (strequal(fname,".com") ||
2235                     strequal(fname,".dll") ||
2236                     strequal(fname,".exe") ||
2237                     strequal(fname,".sym")) {
2238                         return True;
2239                 }
2240         }
2241         return False;
2242 }
2243
2244 /****************************************************************************
2245  Open a file with a share mode - old openX method - map into NTCreate.
2246 ****************************************************************************/
2247
2248 bool map_open_params_to_ntcreate(const char *smb_base_fname,
2249                                  int deny_mode, int open_func,
2250                                  uint32 *paccess_mask,
2251                                  uint32 *pshare_mode,
2252                                  uint32 *pcreate_disposition,
2253                                  uint32 *pcreate_options,
2254                                  uint32_t *pprivate_flags)
2255 {
2256         uint32 access_mask;
2257         uint32 share_mode;
2258         uint32 create_disposition;
2259         uint32 create_options = FILE_NON_DIRECTORY_FILE;
2260         uint32_t private_flags = 0;
2261
2262         DEBUG(10,("map_open_params_to_ntcreate: fname = %s, deny_mode = 0x%x, "
2263                   "open_func = 0x%x\n",
2264                   smb_base_fname, (unsigned int)deny_mode,
2265                   (unsigned int)open_func ));
2266
2267         /* Create the NT compatible access_mask. */
2268         switch (GET_OPENX_MODE(deny_mode)) {
2269                 case DOS_OPEN_EXEC: /* Implies read-only - used to be FILE_READ_DATA */
2270                 case DOS_OPEN_RDONLY:
2271                         access_mask = FILE_GENERIC_READ;
2272                         break;
2273                 case DOS_OPEN_WRONLY:
2274                         access_mask = FILE_GENERIC_WRITE;
2275                         break;
2276                 case DOS_OPEN_RDWR:
2277                 case DOS_OPEN_FCB:
2278                         access_mask = FILE_GENERIC_READ|FILE_GENERIC_WRITE;
2279                         break;
2280                 default:
2281                         DEBUG(10,("map_open_params_to_ntcreate: bad open mode = 0x%x\n",
2282                                   (unsigned int)GET_OPENX_MODE(deny_mode)));
2283                         return False;
2284         }
2285
2286         /* Create the NT compatible create_disposition. */
2287         switch (open_func) {
2288                 case OPENX_FILE_EXISTS_FAIL|OPENX_FILE_CREATE_IF_NOT_EXIST:
2289                         create_disposition = FILE_CREATE;
2290                         break;
2291
2292                 case OPENX_FILE_EXISTS_OPEN:
2293                         create_disposition = FILE_OPEN;
2294                         break;
2295
2296                 case OPENX_FILE_EXISTS_OPEN|OPENX_FILE_CREATE_IF_NOT_EXIST:
2297                         create_disposition = FILE_OPEN_IF;
2298                         break;
2299
2300                 case OPENX_FILE_EXISTS_TRUNCATE:
2301                         create_disposition = FILE_OVERWRITE;
2302                         break;
2303
2304                 case OPENX_FILE_EXISTS_TRUNCATE|OPENX_FILE_CREATE_IF_NOT_EXIST:
2305                         create_disposition = FILE_OVERWRITE_IF;
2306                         break;
2307
2308                 default:
2309                         /* From samba4 - to be confirmed. */
2310                         if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_EXEC) {
2311                                 create_disposition = FILE_CREATE;
2312                                 break;
2313                         }
2314                         DEBUG(10,("map_open_params_to_ntcreate: bad "
2315                                   "open_func 0x%x\n", (unsigned int)open_func));
2316                         return False;
2317         }
2318
2319         /* Create the NT compatible share modes. */
2320         switch (GET_DENY_MODE(deny_mode)) {
2321                 case DENY_ALL:
2322                         share_mode = FILE_SHARE_NONE;
2323                         break;
2324
2325                 case DENY_WRITE:
2326                         share_mode = FILE_SHARE_READ;
2327                         break;
2328
2329                 case DENY_READ:
2330                         share_mode = FILE_SHARE_WRITE;
2331                         break;
2332
2333                 case DENY_NONE:
2334                         share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2335                         break;
2336
2337                 case DENY_DOS:
2338                         private_flags |= NTCREATEX_OPTIONS_PRIVATE_DENY_DOS;
2339                         if (is_executable(smb_base_fname)) {
2340                                 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2341                         } else {
2342                                 if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_RDONLY) {
2343                                         share_mode = FILE_SHARE_READ;
2344                                 } else {
2345                                         share_mode = FILE_SHARE_NONE;
2346                                 }
2347                         }
2348                         break;
2349
2350                 case DENY_FCB:
2351                         private_flags |= NTCREATEX_OPTIONS_PRIVATE_DENY_FCB;
2352                         share_mode = FILE_SHARE_NONE;
2353                         break;
2354
2355                 default:
2356                         DEBUG(10,("map_open_params_to_ntcreate: bad deny_mode 0x%x\n",
2357                                 (unsigned int)GET_DENY_MODE(deny_mode) ));
2358                         return False;
2359         }
2360
2361         DEBUG(10,("map_open_params_to_ntcreate: file %s, access_mask = 0x%x, "
2362                   "share_mode = 0x%x, create_disposition = 0x%x, "
2363                   "create_options = 0x%x private_flags = 0x%x\n",
2364                   smb_base_fname,
2365                   (unsigned int)access_mask,
2366                   (unsigned int)share_mode,
2367                   (unsigned int)create_disposition,
2368                   (unsigned int)create_options,
2369                   (unsigned int)private_flags));
2370
2371         if (paccess_mask) {
2372                 *paccess_mask = access_mask;
2373         }
2374         if (pshare_mode) {
2375                 *pshare_mode = share_mode;
2376         }
2377         if (pcreate_disposition) {
2378                 *pcreate_disposition = create_disposition;
2379         }
2380         if (pcreate_options) {
2381                 *pcreate_options = create_options;
2382         }
2383         if (pprivate_flags) {
2384                 *pprivate_flags = private_flags;
2385         }
2386
2387         return True;
2388
2389 }
2390
2391
2392 void init_modules(void)
2393 {
2394         /* FIXME: This can cause undefined symbol errors :
2395          *  smb_register_vfs() isn't available in nmbd, for example */
2396         if(lp_preload_modules())
2397                 smb_load_modules(lp_preload_modules());
2398 }