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