Remove unused get_file_size() function.
[tridge/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  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  Is the name specified our workgroup/domain.
1219  Returns true if it is equal, false otherwise.
1220 ********************************************************************/
1221
1222 bool is_myworkgroup(const char *s)
1223 {
1224         bool ret = False;
1225
1226         if (strequal(s, lp_workgroup())) {
1227                 ret=True;
1228         }
1229
1230         DEBUG(8, ("is_myworkgroup(\"%s\") returns %d\n", s, ret));
1231         return(ret);
1232 }
1233
1234 /*******************************************************************
1235  we distinguish between 2K and XP by the "Native Lan Manager" string
1236    WinXP => "Windows 2002 5.1"
1237    WinXP 64bit => "Windows XP 5.2"
1238    Win2k => "Windows 2000 5.0"
1239    NT4   => "Windows NT 4.0"
1240    Win9x => "Windows 4.0"
1241  Windows 2003 doesn't set the native lan manager string but
1242  they do set the domain to "Windows 2003 5.2" (probably a bug).
1243 ********************************************************************/
1244
1245 void ra_lanman_string( const char *native_lanman )
1246 {
1247         if ( strcmp( native_lanman, "Windows 2002 5.1" ) == 0 )
1248                 set_remote_arch( RA_WINXP );
1249         else if ( strcmp( native_lanman, "Windows XP 5.2" ) == 0 )
1250                 set_remote_arch( RA_WINXP64 );
1251         else if ( strcmp( native_lanman, "Windows Server 2003 5.2" ) == 0 )
1252                 set_remote_arch( RA_WIN2K3 );
1253 }
1254
1255 static const char *remote_arch_str;
1256
1257 const char *get_remote_arch_str(void)
1258 {
1259         if (!remote_arch_str) {
1260                 return "UNKNOWN";
1261         }
1262         return remote_arch_str;
1263 }
1264
1265 /*******************************************************************
1266  Set the horrid remote_arch string based on an enum.
1267 ********************************************************************/
1268
1269 void set_remote_arch(enum remote_arch_types type)
1270 {
1271         ra_type = type;
1272         switch( type ) {
1273         case RA_WFWG:
1274                 remote_arch_str = "WfWg";
1275                 break;
1276         case RA_OS2:
1277                 remote_arch_str = "OS2";
1278                 break;
1279         case RA_WIN95:
1280                 remote_arch_str = "Win95";
1281                 break;
1282         case RA_WINNT:
1283                 remote_arch_str = "WinNT";
1284                 break;
1285         case RA_WIN2K:
1286                 remote_arch_str = "Win2K";
1287                 break;
1288         case RA_WINXP:
1289                 remote_arch_str = "WinXP";
1290                 break;
1291         case RA_WINXP64:
1292                 remote_arch_str = "WinXP64";
1293                 break;
1294         case RA_WIN2K3:
1295                 remote_arch_str = "Win2K3";
1296                 break;
1297         case RA_VISTA:
1298                 remote_arch_str = "Vista";
1299                 break;
1300         case RA_SAMBA:
1301                 remote_arch_str = "Samba";
1302                 break;
1303         case RA_CIFSFS:
1304                 remote_arch_str = "CIFSFS";
1305                 break;
1306         case RA_OSX:
1307                 remote_arch_str = "OSX";
1308                 break;
1309         default:
1310                 ra_type = RA_UNKNOWN;
1311                 remote_arch_str = "UNKNOWN";
1312                 break;
1313         }
1314
1315         DEBUG(10,("set_remote_arch: Client arch is \'%s\'\n",
1316                                 remote_arch_str));
1317 }
1318
1319 /*******************************************************************
1320  Get the remote_arch type.
1321 ********************************************************************/
1322
1323 enum remote_arch_types get_remote_arch(void)
1324 {
1325         return ra_type;
1326 }
1327
1328 const char *tab_depth(int level, int depth)
1329 {
1330         if( CHECK_DEBUGLVL(level) ) {
1331                 dbgtext("%*s", depth*4, "");
1332         }
1333         return "";
1334 }
1335
1336 /*****************************************************************************
1337  Provide a checksum on a string
1338
1339  Input:  s - the null-terminated character string for which the checksum
1340              will be calculated.
1341
1342   Output: The checksum value calculated for s.
1343 *****************************************************************************/
1344
1345 int str_checksum(const char *s)
1346 {
1347         if (s == NULL)
1348                 return 0;
1349         return hash(s, strlen(s), 0);
1350 }
1351
1352 /*****************************************************************
1353  Zero a memory area then free it. Used to catch bugs faster.
1354 *****************************************************************/  
1355
1356 void zero_free(void *p, size_t size)
1357 {
1358         memset(p, 0, size);
1359         SAFE_FREE(p);
1360 }
1361
1362 /*****************************************************************
1363  Set our open file limit to a requested max and return the limit.
1364 *****************************************************************/  
1365
1366 int set_maxfiles(int requested_max)
1367 {
1368 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
1369         struct rlimit rlp;
1370         int saved_current_limit;
1371
1372         if(getrlimit(RLIMIT_NOFILE, &rlp)) {
1373                 DEBUG(0,("set_maxfiles: getrlimit (1) for RLIMIT_NOFILE failed with error %s\n",
1374                         strerror(errno) ));
1375                 /* just guess... */
1376                 return requested_max;
1377         }
1378
1379         /* 
1380          * Set the fd limit to be real_max_open_files + MAX_OPEN_FUDGEFACTOR to
1381          * account for the extra fd we need 
1382          * as well as the log files and standard
1383          * handles etc. Save the limit we want to set in case
1384          * we are running on an OS that doesn't support this limit (AIX)
1385          * which always returns RLIM_INFINITY for rlp.rlim_max.
1386          */
1387
1388         /* Try raising the hard (max) limit to the requested amount. */
1389
1390 #if defined(RLIM_INFINITY)
1391         if (rlp.rlim_max != RLIM_INFINITY) {
1392                 int orig_max = rlp.rlim_max;
1393
1394                 if ( rlp.rlim_max < requested_max )
1395                         rlp.rlim_max = requested_max;
1396
1397                 /* This failing is not an error - many systems (Linux) don't
1398                         support our default request of 10,000 open files. JRA. */
1399
1400                 if(setrlimit(RLIMIT_NOFILE, &rlp)) {
1401                         DEBUG(3,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d max files failed with error %s\n", 
1402                                 (int)rlp.rlim_max, strerror(errno) ));
1403
1404                         /* Set failed - restore original value from get. */
1405                         rlp.rlim_max = orig_max;
1406                 }
1407         }
1408 #endif
1409
1410         /* Now try setting the soft (current) limit. */
1411
1412         saved_current_limit = rlp.rlim_cur = MIN(requested_max,rlp.rlim_max);
1413
1414         if(setrlimit(RLIMIT_NOFILE, &rlp)) {
1415                 DEBUG(0,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d files failed with error %s\n", 
1416                         (int)rlp.rlim_cur, strerror(errno) ));
1417                 /* just guess... */
1418                 return saved_current_limit;
1419         }
1420
1421         if(getrlimit(RLIMIT_NOFILE, &rlp)) {
1422                 DEBUG(0,("set_maxfiles: getrlimit (2) for RLIMIT_NOFILE failed with error %s\n",
1423                         strerror(errno) ));
1424                 /* just guess... */
1425                 return saved_current_limit;
1426     }
1427
1428 #if defined(RLIM_INFINITY)
1429         if(rlp.rlim_cur == RLIM_INFINITY)
1430                 return saved_current_limit;
1431 #endif
1432
1433         if((int)rlp.rlim_cur > saved_current_limit)
1434                 return saved_current_limit;
1435
1436         return rlp.rlim_cur;
1437 #else /* !defined(HAVE_GETRLIMIT) || !defined(RLIMIT_NOFILE) */
1438         /*
1439          * No way to know - just guess...
1440          */
1441         return requested_max;
1442 #endif
1443 }
1444
1445 /*****************************************************************
1446  malloc that aborts with smb_panic on fail or zero size.
1447  *****************************************************************/  
1448
1449 void *smb_xmalloc_array(size_t size, unsigned int count)
1450 {
1451         void *p;
1452         if (size == 0) {
1453                 smb_panic("smb_xmalloc_array: called with zero size");
1454         }
1455         if (count >= MAX_ALLOC_SIZE/size) {
1456                 smb_panic("smb_xmalloc_array: alloc size too large");
1457         }
1458         if ((p = SMB_MALLOC(size*count)) == NULL) {
1459                 DEBUG(0, ("smb_xmalloc_array failed to allocate %lu * %lu bytes\n",
1460                         (unsigned long)size, (unsigned long)count));
1461                 smb_panic("smb_xmalloc_array: malloc failed");
1462         }
1463         return p;
1464 }
1465
1466 /*
1467   vasprintf that aborts on malloc fail
1468 */
1469
1470  int smb_xvasprintf(char **ptr, const char *format, va_list ap)
1471 {
1472         int n;
1473         va_list ap2;
1474
1475         va_copy(ap2, ap);
1476
1477         n = vasprintf(ptr, format, ap2);
1478         va_end(ap2);
1479         if (n == -1 || ! *ptr) {
1480                 smb_panic("smb_xvasprintf: out of memory");
1481         }
1482         return n;
1483 }
1484
1485 /*****************************************************************
1486  Get local hostname and cache result.
1487 *****************************************************************/
1488
1489 char *myhostname(void)
1490 {
1491         static char *ret;
1492         if (ret == NULL) {
1493                 ret = get_myname(NULL);
1494         }
1495         return ret;
1496 }
1497
1498 /*****************************************************************
1499  Get local hostname and cache result.
1500 *****************************************************************/
1501
1502 char *myhostname_upper(void)
1503 {
1504         char *name;
1505         static char *ret;
1506         if (ret == NULL) {
1507                 name = get_myname(talloc_tos());
1508                 ret = strupper_talloc(NULL, name);
1509                 talloc_free(name);
1510         }
1511         return ret;
1512 }
1513
1514 /**
1515  * @brief Returns an absolute path to a file concatenating the provided
1516  * @a rootpath and @a basename
1517  *
1518  * @param name Filename, relative to @a rootpath
1519  *
1520  * @retval Pointer to a string containing the full path.
1521  **/
1522
1523 static char *xx_path(const char *name, const char *rootpath)
1524 {
1525         char *fname = NULL;
1526
1527         fname = talloc_strdup(talloc_tos(), rootpath);
1528         if (!fname) {
1529                 return NULL;
1530         }
1531         trim_string(fname,"","/");
1532
1533         if (!directory_exist(fname)) {
1534                 if (!mkdir(fname,0755))
1535                         DEBUG(1, ("Unable to create directory %s for file %s. "
1536                               "Error was %s\n", fname, name, strerror(errno)));
1537         }
1538
1539         return talloc_asprintf(talloc_tos(),
1540                                 "%s/%s",
1541                                 fname,
1542                                 name);
1543 }
1544
1545 /**
1546  * @brief Returns an absolute path to a file in the Samba lock directory.
1547  *
1548  * @param name File to find, relative to LOCKDIR.
1549  *
1550  * @retval Pointer to a talloc'ed string containing the full path.
1551  **/
1552
1553 char *lock_path(const char *name)
1554 {
1555         return xx_path(name, lp_lockdir());
1556 }
1557
1558 /**
1559  * @brief Returns an absolute path to a file in the Samba pid directory.
1560  *
1561  * @param name File to find, relative to PIDDIR.
1562  *
1563  * @retval Pointer to a talloc'ed string containing the full path.
1564  **/
1565
1566 char *pid_path(const char *name)
1567 {
1568         return xx_path(name, lp_piddir());
1569 }
1570
1571 /**
1572  * @brief Returns an absolute path to a file in the Samba state directory.
1573  *
1574  * @param name File to find, relative to STATEDIR.
1575  *
1576  * @retval Pointer to a talloc'ed string containing the full path.
1577  **/
1578
1579 char *state_path(const char *name)
1580 {
1581         return xx_path(name, lp_statedir());
1582 }
1583
1584 /**
1585  * @brief Returns an absolute path to a file in the Samba cache directory.
1586  *
1587  * @param name File to find, relative to CACHEDIR.
1588  *
1589  * @retval Pointer to a talloc'ed string containing the full path.
1590  **/
1591
1592 char *cache_path(const char *name)
1593 {
1594         return xx_path(name, lp_cachedir());
1595 }
1596
1597 /*******************************************************************
1598  Given a filename - get its directory name
1599 ********************************************************************/
1600
1601 bool parent_dirname(TALLOC_CTX *mem_ctx, const char *dir, char **parent,
1602                     const char **name)
1603 {
1604         char *p;
1605         ptrdiff_t len;
1606
1607         p = strrchr_m(dir, '/'); /* Find final '/', if any */
1608
1609         if (p == NULL) {
1610                 if (!(*parent = talloc_strdup(mem_ctx, "."))) {
1611                         return False;
1612                 }
1613                 if (name) {
1614                         *name = dir;
1615                 }
1616                 return True;
1617         }
1618
1619         len = p-dir;
1620
1621         if (!(*parent = (char *)talloc_memdup(mem_ctx, dir, len+1))) {
1622                 return False;
1623         }
1624         (*parent)[len] = '\0';
1625
1626         if (name) {
1627                 *name = p+1;
1628         }
1629         return True;
1630 }
1631
1632 /*******************************************************************
1633  Determine if a pattern contains any Microsoft wildcard characters.
1634 *******************************************************************/
1635
1636 bool ms_has_wild(const char *s)
1637 {
1638         char c;
1639
1640         if (lp_posix_pathnames()) {
1641                 /* With posix pathnames no characters are wild. */
1642                 return False;
1643         }
1644
1645         while ((c = *s++)) {
1646                 switch (c) {
1647                 case '*':
1648                 case '?':
1649                 case '<':
1650                 case '>':
1651                 case '"':
1652                         return True;
1653                 }
1654         }
1655         return False;
1656 }
1657
1658 bool ms_has_wild_w(const smb_ucs2_t *s)
1659 {
1660         smb_ucs2_t c;
1661         if (!s) return False;
1662         while ((c = *s++)) {
1663                 switch (c) {
1664                 case UCS2_CHAR('*'):
1665                 case UCS2_CHAR('?'):
1666                 case UCS2_CHAR('<'):
1667                 case UCS2_CHAR('>'):
1668                 case UCS2_CHAR('"'):
1669                         return True;
1670                 }
1671         }
1672         return False;
1673 }
1674
1675 /*******************************************************************
1676  A wrapper that handles case sensitivity and the special handling
1677  of the ".." name.
1678 *******************************************************************/
1679
1680 bool mask_match(const char *string, const char *pattern, bool is_case_sensitive)
1681 {
1682         if (ISDOTDOT(string))
1683                 string = ".";
1684         if (ISDOT(pattern))
1685                 return False;
1686
1687         return ms_fnmatch(pattern, string, Protocol <= PROTOCOL_LANMAN2, is_case_sensitive) == 0;
1688 }
1689
1690 /*******************************************************************
1691  A wrapper that handles case sensitivity and the special handling
1692  of the ".." name. Varient that is only called by old search code which requires
1693  pattern translation.
1694 *******************************************************************/
1695
1696 bool mask_match_search(const char *string, const char *pattern, bool is_case_sensitive)
1697 {
1698         if (ISDOTDOT(string))
1699                 string = ".";
1700         if (ISDOT(pattern))
1701                 return False;
1702
1703         return ms_fnmatch(pattern, string, True, is_case_sensitive) == 0;
1704 }
1705
1706 /*******************************************************************
1707  A wrapper that handles a list of patters and calls mask_match()
1708  on each.  Returns True if any of the patterns match.
1709 *******************************************************************/
1710
1711 bool mask_match_list(const char *string, char **list, int listLen, bool is_case_sensitive)
1712 {
1713        while (listLen-- > 0) {
1714                if (mask_match(string, *list++, is_case_sensitive))
1715                        return True;
1716        }
1717        return False;
1718 }
1719
1720 /*********************************************************
1721  Recursive routine that is called by unix_wild_match.
1722 *********************************************************/
1723
1724 static bool unix_do_match(const char *regexp, const char *str)
1725 {
1726         const char *p;
1727
1728         for( p = regexp; *p && *str; ) {
1729
1730                 switch(*p) {
1731                         case '?':
1732                                 str++;
1733                                 p++;
1734                                 break;
1735
1736                         case '*':
1737
1738                                 /*
1739                                  * Look for a character matching 
1740                                  * the one after the '*'.
1741                                  */
1742                                 p++;
1743                                 if(!*p)
1744                                         return true; /* Automatic match */
1745                                 while(*str) {
1746
1747                                         while(*str && (*p != *str))
1748                                                 str++;
1749
1750                                         /*
1751                                          * Patch from weidel@multichart.de. In the case of the regexp
1752                                          * '*XX*' we want to ensure there are at least 2 'X' characters
1753                                          * in the string after the '*' for a match to be made.
1754                                          */
1755
1756                                         {
1757                                                 int matchcount=0;
1758
1759                                                 /*
1760                                                  * Eat all the characters that match, but count how many there were.
1761                                                  */
1762
1763                                                 while(*str && (*p == *str)) {
1764                                                         str++;
1765                                                         matchcount++;
1766                                                 }
1767
1768                                                 /*
1769                                                  * Now check that if the regexp had n identical characters that
1770                                                  * matchcount had at least that many matches.
1771                                                  */
1772
1773                                                 while ( *(p+1) && (*(p+1) == *p)) {
1774                                                         p++;
1775                                                         matchcount--;
1776                                                 }
1777
1778                                                 if ( matchcount <= 0 )
1779                                                         return false;
1780                                         }
1781
1782                                         str--; /* We've eaten the match char after the '*' */
1783
1784                                         if(unix_do_match(p, str))
1785                                                 return true;
1786
1787                                         if(!*str)
1788                                                 return false;
1789                                         else
1790                                                 str++;
1791                                 }
1792                                 return false;
1793
1794                         default:
1795                                 if(*str != *p)
1796                                         return false;
1797                                 str++;
1798                                 p++;
1799                                 break;
1800                 }
1801         }
1802
1803         if(!*p && !*str)
1804                 return true;
1805
1806         if (!*p && str[0] == '.' && str[1] == 0)
1807                 return true;
1808
1809         if (!*str && *p == '?') {
1810                 while (*p == '?')
1811                         p++;
1812                 return(!*p);
1813         }
1814
1815         if(!*str && (*p == '*' && p[1] == '\0'))
1816                 return true;
1817
1818         return false;
1819 }
1820
1821 /*******************************************************************
1822  Simple case insensitive interface to a UNIX wildcard matcher.
1823  Returns True if match, False if not.
1824 *******************************************************************/
1825
1826 bool unix_wild_match(const char *pattern, const char *string)
1827 {
1828         TALLOC_CTX *ctx = talloc_stackframe();
1829         char *p2;
1830         char *s2;
1831         char *p;
1832         bool ret = false;
1833
1834         p2 = talloc_strdup(ctx,pattern);
1835         s2 = talloc_strdup(ctx,string);
1836         if (!p2 || !s2) {
1837                 TALLOC_FREE(ctx);
1838                 return false;
1839         }
1840         strlower_m(p2);
1841         strlower_m(s2);
1842
1843         /* Remove any *? and ** from the pattern as they are meaningless */
1844         for(p = p2; *p; p++) {
1845                 while( *p == '*' && (p[1] == '?' ||p[1] == '*')) {
1846                         memmove(&p[1], &p[2], strlen(&p[2])+1);
1847                 }
1848         }
1849
1850         if (strequal(p2,"*")) {
1851                 TALLOC_FREE(ctx);
1852                 return true;
1853         }
1854
1855         ret = unix_do_match(p2, s2);
1856         TALLOC_FREE(ctx);
1857         return ret;
1858 }
1859
1860 /**********************************************************************
1861  Converts a name to a fully qualified domain name.
1862  Returns true if lookup succeeded, false if not (then fqdn is set to name)
1863  Note we deliberately use gethostbyname here, not getaddrinfo as we want
1864  to examine the h_aliases and I don't know how to do that with getaddrinfo.
1865 ***********************************************************************/
1866
1867 bool name_to_fqdn(fstring fqdn, const char *name)
1868 {
1869         char *full = NULL;
1870         struct hostent *hp = gethostbyname(name);
1871
1872         if (!hp || !hp->h_name || !*hp->h_name) {
1873                 DEBUG(10,("name_to_fqdn: lookup for %s failed.\n", name));
1874                 fstrcpy(fqdn, name);
1875                 return false;
1876         }
1877
1878         /* Find out if the fqdn is returned as an alias
1879          * to cope with /etc/hosts files where the first
1880          * name is not the fqdn but the short name */
1881         if (hp->h_aliases && (! strchr_m(hp->h_name, '.'))) {
1882                 int i;
1883                 for (i = 0; hp->h_aliases[i]; i++) {
1884                         if (strchr_m(hp->h_aliases[i], '.')) {
1885                                 full = hp->h_aliases[i];
1886                                 break;
1887                         }
1888                 }
1889         }
1890         if (full && (strcasecmp_m(full, "localhost.localdomain") == 0)) {
1891                 DEBUG(1, ("WARNING: your /etc/hosts file may be broken!\n"));
1892                 DEBUGADD(1, ("    Specifing the machine hostname for address 127.0.0.1 may lead\n"));
1893                 DEBUGADD(1, ("    to Kerberos authentication problems as localhost.localdomain\n"));
1894                 DEBUGADD(1, ("    may end up being used instead of the real machine FQDN.\n"));
1895                 full = hp->h_name;
1896         }
1897         if (!full) {
1898                 full = hp->h_name;
1899         }
1900
1901         DEBUG(10,("name_to_fqdn: lookup for %s -> %s.\n", name, full));
1902         fstrcpy(fqdn, full);
1903         return true;
1904 }
1905
1906 /**********************************************************************
1907  Append a DATA_BLOB to a talloc'ed object
1908 ***********************************************************************/
1909
1910 void *talloc_append_blob(TALLOC_CTX *mem_ctx, void *buf, DATA_BLOB blob)
1911 {
1912         size_t old_size = 0;
1913         char *result;
1914
1915         if (blob.length == 0) {
1916                 return buf;
1917         }
1918
1919         if (buf != NULL) {
1920                 old_size = talloc_get_size(buf);
1921         }
1922
1923         result = (char *)TALLOC_REALLOC(mem_ctx, buf, old_size + blob.length);
1924         if (result == NULL) {
1925                 return NULL;
1926         }
1927
1928         memcpy(result + old_size, blob.data, blob.length);
1929         return result;
1930 }
1931
1932 uint32 map_share_mode_to_deny_mode(uint32 share_access, uint32 private_options)
1933 {
1934         switch (share_access & ~FILE_SHARE_DELETE) {
1935                 case FILE_SHARE_NONE:
1936                         return DENY_ALL;
1937                 case FILE_SHARE_READ:
1938                         return DENY_WRITE;
1939                 case FILE_SHARE_WRITE:
1940                         return DENY_READ;
1941                 case FILE_SHARE_READ|FILE_SHARE_WRITE:
1942                         return DENY_NONE;
1943         }
1944         if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS) {
1945                 return DENY_DOS;
1946         } else if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_FCB) {
1947                 return DENY_FCB;
1948         }
1949
1950         return (uint32)-1;
1951 }
1952
1953 pid_t procid_to_pid(const struct server_id *proc)
1954 {
1955         return proc->pid;
1956 }
1957
1958 static uint32 my_vnn = NONCLUSTER_VNN;
1959
1960 void set_my_vnn(uint32 vnn)
1961 {
1962         DEBUG(10, ("vnn pid %d = %u\n", (int)sys_getpid(), (unsigned int)vnn));
1963         my_vnn = vnn;
1964 }
1965
1966 uint32 get_my_vnn(void)
1967 {
1968         return my_vnn;
1969 }
1970
1971 static uint64_t my_unique_id = 0;
1972
1973 void set_my_unique_id(uint64_t unique_id)
1974 {
1975         my_unique_id = unique_id;
1976 }
1977
1978 struct server_id pid_to_procid(pid_t pid)
1979 {
1980         struct server_id result;
1981         result.pid = pid;
1982         result.task_id = 0;
1983         result.unique_id = my_unique_id;
1984         result.vnn = my_vnn;
1985         return result;
1986 }
1987
1988 struct server_id procid_self(void)
1989 {
1990         return pid_to_procid(sys_getpid());
1991 }
1992
1993 bool procid_equal(const struct server_id *p1, const struct server_id *p2)
1994 {
1995         if (p1->pid != p2->pid)
1996                 return False;
1997         if (p1->task_id != p2->task_id)
1998                 return False;
1999         if (p1->vnn != p2->vnn)
2000                 return False;
2001         return True;
2002 }
2003
2004 bool cluster_id_equal(const struct server_id *id1,
2005                       const struct server_id *id2)
2006 {
2007         return procid_equal(id1, id2);
2008 }
2009
2010 bool procid_is_me(const struct server_id *pid)
2011 {
2012         if (pid->pid != sys_getpid())
2013                 return False;
2014         if (pid->task_id != 0)
2015                 return False;
2016         if (pid->vnn != my_vnn)
2017                 return False;
2018         return True;
2019 }
2020
2021 struct server_id interpret_pid(const char *pid_string)
2022 {
2023         struct server_id result;
2024         unsigned long long pid;
2025         unsigned int vnn, task_id = 0;
2026
2027         ZERO_STRUCT(result);
2028
2029         /* We accept various forms with 1, 2 or 3 component forms
2030          * because the server_id_str() can print different forms, and
2031          * we want backwards compatibility for scripts that may call
2032          * smbclient. */
2033         if (sscanf(pid_string, "%u:%llu.%u", &vnn, &pid, &task_id) == 3) {
2034                 result.vnn = vnn;
2035                 result.pid = pid;
2036                 result.task_id = task_id;
2037         } else if (sscanf(pid_string, "%u:%llu", &vnn, &pid) == 2) {
2038                 result.vnn = vnn;
2039                 result.pid = pid;
2040                 result.task_id = 0;
2041         } else if (sscanf(pid_string, "%llu.%u", &pid, &task_id) == 2) {
2042                 result.vnn = get_my_vnn();
2043                 result.pid = pid;
2044                 result.task_id = task_id;
2045         } else if (sscanf(pid_string, "%llu", &pid) == 1) {
2046                 result.vnn = get_my_vnn();
2047                 result.pid = pid;
2048         } else {
2049                 result.vnn = NONCLUSTER_VNN;
2050                 result.pid = (uint64_t)-1;
2051         }
2052         return result;
2053 }
2054
2055 char *procid_str_static(const struct server_id *pid)
2056 {
2057         return server_id_str(talloc_tos(), pid);
2058 }
2059
2060 bool procid_valid(const struct server_id *pid)
2061 {
2062         return (pid->pid != (uint64_t)-1);
2063 }
2064
2065 bool procid_is_local(const struct server_id *pid)
2066 {
2067         return pid->vnn == my_vnn;
2068 }
2069
2070 /****************************************************************
2071  Check if an offset into a buffer is safe.
2072  If this returns True it's safe to indirect into the byte at
2073  pointer ptr+off.
2074 ****************************************************************/
2075
2076 bool is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
2077 {
2078         const char *end_base = buf_base + buf_len;
2079         char *end_ptr = ptr + off;
2080
2081         if (!buf_base || !ptr) {
2082                 return False;
2083         }
2084
2085         if (end_base < buf_base || end_ptr < ptr) {
2086                 return False; /* wrap. */
2087         }
2088
2089         if (end_ptr < end_base) {
2090                 return True;
2091         }
2092         return False;
2093 }
2094
2095 /****************************************************************
2096  Return a safe pointer into a buffer, or NULL.
2097 ****************************************************************/
2098
2099 char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
2100 {
2101         return is_offset_safe(buf_base, buf_len, ptr, off) ?
2102                         ptr + off : NULL;
2103 }
2104
2105 /****************************************************************
2106  Return a safe pointer into a string within a buffer, or NULL.
2107 ****************************************************************/
2108
2109 char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
2110 {
2111         if (!is_offset_safe(buf_base, buf_len, ptr, off)) {
2112                 return NULL;
2113         }
2114         /* Check if a valid string exists at this offset. */
2115         if (skip_string(buf_base,buf_len, ptr + off) == NULL) {
2116                 return NULL;
2117         }
2118         return ptr + off;
2119 }
2120
2121 /****************************************************************
2122  Return an SVAL at a pointer, or failval if beyond the end.
2123 ****************************************************************/
2124
2125 int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
2126 {
2127         /*
2128          * Note we use off+1 here, not off+2 as SVAL accesses ptr[0] and ptr[1],
2129          * NOT ptr[2].
2130          */
2131         if (!is_offset_safe(buf_base, buf_len, ptr, off+1)) {
2132                 return failval;
2133         }
2134         return SVAL(ptr,off);
2135 }
2136
2137 /****************************************************************
2138  Return an IVAL at a pointer, or failval if beyond the end.
2139 ****************************************************************/
2140
2141 int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
2142 {
2143         /*
2144          * Note we use off+3 here, not off+4 as IVAL accesses 
2145          * ptr[0] ptr[1] ptr[2] ptr[3] NOT ptr[4].
2146          */
2147         if (!is_offset_safe(buf_base, buf_len, ptr, off+3)) {
2148                 return failval;
2149         }
2150         return IVAL(ptr,off);
2151 }
2152
2153 /****************************************************************
2154  Split DOM\user into DOM and user. Do not mix with winbind variants of that
2155  call (they take care of winbind separator and other winbind specific settings).
2156 ****************************************************************/
2157
2158 void split_domain_user(TALLOC_CTX *mem_ctx,
2159                        const char *full_name,
2160                        char **domain,
2161                        char **user)
2162 {
2163         const char *p = NULL;
2164
2165         p = strchr_m(full_name, '\\');
2166
2167         if (p != NULL) {
2168                 *domain = talloc_strndup(mem_ctx, full_name,
2169                                          PTR_DIFF(p, full_name));
2170                 *user = talloc_strdup(mem_ctx, p+1);
2171         } else {
2172                 *domain = talloc_strdup(mem_ctx, "");
2173                 *user = talloc_strdup(mem_ctx, full_name);
2174         }
2175 }
2176
2177 /****************************************************************
2178  strip off leading '\\' from a hostname
2179 ****************************************************************/
2180
2181 const char *strip_hostname(const char *s)
2182 {
2183         if (!s) {
2184                 return NULL;
2185         }
2186
2187         if (strlen_m(s) < 3) {
2188                 return s;
2189         }
2190
2191         if (s[0] == '\\') s++;
2192         if (s[0] == '\\') s++;
2193
2194         return s;
2195 }
2196
2197 bool tevent_req_poll_ntstatus(struct tevent_req *req,
2198                               struct tevent_context *ev,
2199                               NTSTATUS *status)
2200 {
2201         bool ret = tevent_req_poll(req, ev);
2202         if (!ret) {
2203                 *status = map_nt_error_from_unix(errno);
2204         }
2205         return ret;
2206 }
2207
2208 bool any_nt_status_not_ok(NTSTATUS err1, NTSTATUS err2, NTSTATUS *result)
2209 {
2210         if (!NT_STATUS_IS_OK(err1)) {
2211                 *result = err1;
2212                 return true;
2213         }
2214         if (!NT_STATUS_IS_OK(err2)) {
2215                 *result = err2;
2216                 return true;
2217         }
2218         return false;
2219 }
2220
2221 int timeval_to_msec(struct timeval t)
2222 {
2223         return t.tv_sec * 1000 + (t.tv_usec+999) / 1000;
2224 }
2225
2226 /*******************************************************************
2227  Check a given DOS pathname is valid for a share.
2228 ********************************************************************/
2229
2230 char *valid_share_pathname(TALLOC_CTX *ctx, const char *dos_pathname)
2231 {
2232         char *ptr = NULL;
2233
2234         if (!dos_pathname) {
2235                 return NULL;
2236         }
2237
2238         ptr = talloc_strdup(ctx, dos_pathname);
2239         if (!ptr) {
2240                 return NULL;
2241         }
2242         /* Convert any '\' paths to '/' */
2243         unix_format(ptr);
2244         ptr = unix_clean_name(ctx, ptr);
2245         if (!ptr) {
2246                 return NULL;
2247         }
2248
2249         /* NT is braindead - it wants a C: prefix to a pathname ! So strip it. */
2250         if (strlen(ptr) > 2 && ptr[1] == ':' && ptr[0] != '/')
2251                 ptr += 2;
2252
2253         /* Only absolute paths allowed. */
2254         if (*ptr != '/')
2255                 return NULL;
2256
2257         return ptr;
2258 }
2259
2260 /*******************************************************************
2261  Return True if the filename is one of the special executable types.
2262 ********************************************************************/
2263
2264 bool is_executable(const char *fname)
2265 {
2266         if ((fname = strrchr_m(fname,'.'))) {
2267                 if (strequal(fname,".com") ||
2268                     strequal(fname,".dll") ||
2269                     strequal(fname,".exe") ||
2270                     strequal(fname,".sym")) {
2271                         return True;
2272                 }
2273         }
2274         return False;
2275 }
2276
2277 /****************************************************************************
2278  Open a file with a share mode - old openX method - map into NTCreate.
2279 ****************************************************************************/
2280
2281 bool map_open_params_to_ntcreate(const char *smb_base_fname,
2282                                  int deny_mode, int open_func,
2283                                  uint32 *paccess_mask,
2284                                  uint32 *pshare_mode,
2285                                  uint32 *pcreate_disposition,
2286                                  uint32 *pcreate_options,
2287                                  uint32_t *pprivate_flags)
2288 {
2289         uint32 access_mask;
2290         uint32 share_mode;
2291         uint32 create_disposition;
2292         uint32 create_options = FILE_NON_DIRECTORY_FILE;
2293         uint32_t private_flags = 0;
2294
2295         DEBUG(10,("map_open_params_to_ntcreate: fname = %s, deny_mode = 0x%x, "
2296                   "open_func = 0x%x\n",
2297                   smb_base_fname, (unsigned int)deny_mode,
2298                   (unsigned int)open_func ));
2299
2300         /* Create the NT compatible access_mask. */
2301         switch (GET_OPENX_MODE(deny_mode)) {
2302                 case DOS_OPEN_EXEC: /* Implies read-only - used to be FILE_READ_DATA */
2303                 case DOS_OPEN_RDONLY:
2304                         access_mask = FILE_GENERIC_READ;
2305                         break;
2306                 case DOS_OPEN_WRONLY:
2307                         access_mask = FILE_GENERIC_WRITE;
2308                         break;
2309                 case DOS_OPEN_RDWR:
2310                 case DOS_OPEN_FCB:
2311                         access_mask = FILE_GENERIC_READ|FILE_GENERIC_WRITE;
2312                         break;
2313                 default:
2314                         DEBUG(10,("map_open_params_to_ntcreate: bad open mode = 0x%x\n",
2315                                   (unsigned int)GET_OPENX_MODE(deny_mode)));
2316                         return False;
2317         }
2318
2319         /* Create the NT compatible create_disposition. */
2320         switch (open_func) {
2321                 case OPENX_FILE_EXISTS_FAIL|OPENX_FILE_CREATE_IF_NOT_EXIST:
2322                         create_disposition = FILE_CREATE;
2323                         break;
2324
2325                 case OPENX_FILE_EXISTS_OPEN:
2326                         create_disposition = FILE_OPEN;
2327                         break;
2328
2329                 case OPENX_FILE_EXISTS_OPEN|OPENX_FILE_CREATE_IF_NOT_EXIST:
2330                         create_disposition = FILE_OPEN_IF;
2331                         break;
2332
2333                 case OPENX_FILE_EXISTS_TRUNCATE:
2334                         create_disposition = FILE_OVERWRITE;
2335                         break;
2336
2337                 case OPENX_FILE_EXISTS_TRUNCATE|OPENX_FILE_CREATE_IF_NOT_EXIST:
2338                         create_disposition = FILE_OVERWRITE_IF;
2339                         break;
2340
2341                 default:
2342                         /* From samba4 - to be confirmed. */
2343                         if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_EXEC) {
2344                                 create_disposition = FILE_CREATE;
2345                                 break;
2346                         }
2347                         DEBUG(10,("map_open_params_to_ntcreate: bad "
2348                                   "open_func 0x%x\n", (unsigned int)open_func));
2349                         return False;
2350         }
2351
2352         /* Create the NT compatible share modes. */
2353         switch (GET_DENY_MODE(deny_mode)) {
2354                 case DENY_ALL:
2355                         share_mode = FILE_SHARE_NONE;
2356                         break;
2357
2358                 case DENY_WRITE:
2359                         share_mode = FILE_SHARE_READ;
2360                         break;
2361
2362                 case DENY_READ:
2363                         share_mode = FILE_SHARE_WRITE;
2364                         break;
2365
2366                 case DENY_NONE:
2367                         share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2368                         break;
2369
2370                 case DENY_DOS:
2371                         private_flags |= NTCREATEX_OPTIONS_PRIVATE_DENY_DOS;
2372                         if (is_executable(smb_base_fname)) {
2373                                 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2374                         } else {
2375                                 if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_RDONLY) {
2376                                         share_mode = FILE_SHARE_READ;
2377                                 } else {
2378                                         share_mode = FILE_SHARE_NONE;
2379                                 }
2380                         }
2381                         break;
2382
2383                 case DENY_FCB:
2384                         private_flags |= NTCREATEX_OPTIONS_PRIVATE_DENY_FCB;
2385                         share_mode = FILE_SHARE_NONE;
2386                         break;
2387
2388                 default:
2389                         DEBUG(10,("map_open_params_to_ntcreate: bad deny_mode 0x%x\n",
2390                                 (unsigned int)GET_DENY_MODE(deny_mode) ));
2391                         return False;
2392         }
2393
2394         DEBUG(10,("map_open_params_to_ntcreate: file %s, access_mask = 0x%x, "
2395                   "share_mode = 0x%x, create_disposition = 0x%x, "
2396                   "create_options = 0x%x private_flags = 0x%x\n",
2397                   smb_base_fname,
2398                   (unsigned int)access_mask,
2399                   (unsigned int)share_mode,
2400                   (unsigned int)create_disposition,
2401                   (unsigned int)create_options,
2402                   (unsigned int)private_flags));
2403
2404         if (paccess_mask) {
2405                 *paccess_mask = access_mask;
2406         }
2407         if (pshare_mode) {
2408                 *pshare_mode = share_mode;
2409         }
2410         if (pcreate_disposition) {
2411                 *pcreate_disposition = create_disposition;
2412         }
2413         if (pcreate_options) {
2414                 *pcreate_options = create_options;
2415         }
2416         if (pprivate_flags) {
2417                 *pprivate_flags = private_flags;
2418         }
2419
2420         return True;
2421
2422 }
2423
2424
2425 void init_modules(void)
2426 {
2427         /* FIXME: This can cause undefined symbol errors :
2428          *  smb_register_vfs() isn't available in nmbd, for example */
2429         if(lp_preload_modules())
2430                 smb_load_modules(lp_preload_modules());
2431 }