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