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