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