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