param: rename lp function and variable from "nis_home_map_name" to "homedir_map"
[vlendec/samba-autobuild/.git] / source3 / lib / util.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Samba utility functions
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Jeremy Allison 2001-2007
6    Copyright (C) Simo Sorce 2001
7    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
8    Copyright (C) James Peach 2006
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "system/passwd.h"
26 #include "system/filesys.h"
27 #include "util_tdb.h"
28 #include "ctdbd_conn.h"
29 #include "../lib/util/util_pw.h"
30 #include "messages.h"
31 #include <ccan/hash/hash.h>
32 #include "libcli/security/security.h"
33 #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 tevent_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 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
563 /******************************************************************
564  Remove any mount options such as -rsize=2048,wsize=2048 etc.
565  Based on a fix from <Thomas.Hepper@icem.de>.
566  Returns a malloc'ed string.
567 *******************************************************************/
568
569 static char *strip_mount_options(TALLOC_CTX *ctx, const char *str)
570 {
571         if (*str == '-') {
572                 const char *p = str;
573                 while(*p && !isspace(*p))
574                         p++;
575                 while(*p && isspace(*p))
576                         p++;
577                 if(*p) {
578                         return talloc_strdup(ctx, p);
579                 }
580         }
581         return NULL;
582 }
583
584 /*******************************************************************
585  Patch from jkf@soton.ac.uk
586  Split Luke's automount_server into YP lookup and string splitter
587  so can easily implement automount_path().
588  Returns a malloc'ed string.
589 *******************************************************************/
590
591 #ifdef WITH_NISPLUS_HOME
592 char *automount_lookup(TALLOC_CTX *ctx, const char *user_name)
593 {
594         char *value = NULL;
595
596         char *nis_map = (char *)lp_homedir_map();
597
598         char buffer[NIS_MAXATTRVAL + 1];
599         nis_result *result;
600         nis_object *object;
601         entry_obj  *entry;
602
603         snprintf(buffer, sizeof(buffer), "[key=%s],%s", user_name, nis_map);
604         DEBUG(5, ("NIS+ querystring: %s\n", buffer));
605
606         if (result = nis_list(buffer, FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP, NULL, NULL)) {
607                 if (result->status != NIS_SUCCESS) {
608                         DEBUG(3, ("NIS+ query failed: %s\n", nis_sperrno(result->status)));
609                 } else {
610                         object = result->objects.objects_val;
611                         if (object->zo_data.zo_type == ENTRY_OBJ) {
612                                 entry = &object->zo_data.objdata_u.en_data;
613                                 DEBUG(5, ("NIS+ entry type: %s\n", entry->en_type));
614                                 DEBUG(3, ("NIS+ result: %s\n", entry->en_cols.en_cols_val[1].ec_value.ec_value_val));
615
616                                 value = talloc_strdup(ctx,
617                                                 entry->en_cols.en_cols_val[1].ec_value.ec_value_val);
618                                 if (!value) {
619                                         nis_freeresult(result);
620                                         return NULL;
621                                 }
622                                 value = talloc_string_sub(ctx,
623                                                 value,
624                                                 "&",
625                                                 user_name);
626                         }
627                 }
628         }
629         nis_freeresult(result);
630
631         if (value) {
632                 value = strip_mount_options(ctx, value);
633                 DEBUG(4, ("NIS+ Lookup: %s resulted in %s\n",
634                                         user_name, value));
635         }
636         return value;
637 }
638 #else /* WITH_NISPLUS_HOME */
639
640 char *automount_lookup(TALLOC_CTX *ctx, const char *user_name)
641 {
642         char *value = NULL;
643
644         int nis_error;        /* returned by yp all functions */
645         char *nis_result;     /* yp_match inits this */
646         int nis_result_len;  /* and set this */
647         char *nis_domain;     /* yp_get_default_domain inits this */
648         char *nis_map = lp_homedir_map(talloc_tos());
649
650         if ((nis_error = yp_get_default_domain(&nis_domain)) != 0) {
651                 DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
652                 return NULL;
653         }
654
655         DEBUG(5, ("NIS Domain: %s\n", nis_domain));
656
657         if ((nis_error = yp_match(nis_domain, nis_map, user_name,
658                                         strlen(user_name), &nis_result,
659                                         &nis_result_len)) == 0) {
660                 if (nis_result_len > 0 && nis_result[nis_result_len] == '\n') {
661                         nis_result[nis_result_len] = '\0';
662                 }
663                 value = talloc_strdup(ctx, nis_result);
664                 if (!value) {
665                         return NULL;
666                 }
667                 value = strip_mount_options(ctx, value);
668         } else if(nis_error == YPERR_KEY) {
669                 DEBUG(3, ("YP Key not found:  while looking up \"%s\" in map \"%s\"\n", 
670                                 user_name, nis_map));
671                 DEBUG(3, ("using defaults for server and home directory\n"));
672         } else {
673                 DEBUG(3, ("YP Error: \"%s\" while looking up \"%s\" in map \"%s\"\n", 
674                                 yperr_string(nis_error), user_name, nis_map));
675         }
676
677         if (value) {
678                 DEBUG(4, ("YP Lookup: %s resulted in %s\n", user_name, value));
679         }
680         return value;
681 }
682 #endif /* WITH_NISPLUS_HOME */
683 #endif
684
685 bool process_exists(const struct server_id pid)
686 {
687         return serverid_exists(&pid);
688 }
689
690 /*******************************************************************
691  Convert a uid into a user name.
692 ********************************************************************/
693
694 const char *uidtoname(uid_t uid)
695 {
696         TALLOC_CTX *ctx = talloc_tos();
697         char *name = NULL;
698         struct passwd *pass = NULL;
699
700         pass = getpwuid_alloc(ctx,uid);
701         if (pass) {
702                 name = talloc_strdup(ctx,pass->pw_name);
703                 TALLOC_FREE(pass);
704         } else {
705                 name = talloc_asprintf(ctx,
706                                 "%ld",
707                                 (long int)uid);
708         }
709         return name;
710 }
711
712 /*******************************************************************
713  Convert a gid into a group name.
714 ********************************************************************/
715
716 char *gidtoname(gid_t gid)
717 {
718         struct group *grp;
719
720         grp = getgrgid(gid);
721         if (grp) {
722                 return talloc_strdup(talloc_tos(), grp->gr_name);
723         }
724         else {
725                 return talloc_asprintf(talloc_tos(),
726                                         "%d",
727                                         (int)gid);
728         }
729 }
730
731 /*******************************************************************
732  Convert a user name into a uid.
733 ********************************************************************/
734
735 uid_t nametouid(const char *name)
736 {
737         struct passwd *pass;
738         char *p;
739         uid_t u;
740
741         pass = Get_Pwnam_alloc(talloc_tos(), name);
742         if (pass) {
743                 u = pass->pw_uid;
744                 TALLOC_FREE(pass);
745                 return u;
746         }
747
748         u = (uid_t)strtol(name, &p, 0);
749         if ((p != name) && (*p == '\0'))
750                 return u;
751
752         return (uid_t)-1;
753 }
754
755 /*******************************************************************
756  Convert a name to a gid_t if possible. Return -1 if not a group. 
757 ********************************************************************/
758
759 gid_t nametogid(const char *name)
760 {
761         struct group *grp;
762         char *p;
763         gid_t g;
764
765         g = (gid_t)strtol(name, &p, 0);
766         if ((p != name) && (*p == '\0'))
767                 return g;
768
769         grp = getgrnam(name);
770         if (grp)
771                 return(grp->gr_gid);
772         return (gid_t)-1;
773 }
774
775 /*******************************************************************
776  Something really nasty happened - panic !
777 ********************************************************************/
778
779 void smb_panic_s3(const char *why)
780 {
781         char *cmd;
782         int result;
783
784         DEBUG(0,("PANIC (pid %llu): %s\n",
785                     (unsigned long long)getpid(), why));
786         log_stack_trace();
787
788 #if defined(HAVE_PRCTL) && defined(PR_SET_PTRACER)
789         /*
790          * Make sure all children can attach a debugger.
791          */
792         prctl(PR_SET_PTRACER, getpid(), 0, 0, 0);
793 #endif
794
795         cmd = lp_panic_action(talloc_tos());
796         if (cmd && *cmd) {
797                 DEBUG(0, ("smb_panic(): calling panic action [%s]\n", cmd));
798                 result = system(cmd);
799
800                 if (result == -1)
801                         DEBUG(0, ("smb_panic(): fork failed in panic action: %s\n",
802                                           strerror(errno)));
803                 else
804                         DEBUG(0, ("smb_panic(): action returned status %d\n",
805                                           WEXITSTATUS(result)));
806         }
807
808         dump_core();
809 }
810
811 /*******************************************************************
812  Print a backtrace of the stack to the debug log. This function
813  DELIBERATELY LEAKS MEMORY. The expectation is that you should
814  exit shortly after calling it.
815 ********************************************************************/
816
817 #ifdef HAVE_LIBUNWIND_H
818 #include <libunwind.h>
819 #endif
820
821 #ifdef HAVE_EXECINFO_H
822 #include <execinfo.h>
823 #endif
824
825 #ifdef HAVE_LIBEXC_H
826 #include <libexc.h>
827 #endif
828
829 void log_stack_trace(void)
830 {
831 #ifdef HAVE_LIBUNWIND
832         /* Try to use libunwind before any other technique since on ia64
833          * libunwind correctly walks the stack in more circumstances than
834          * backtrace.
835          */ 
836         unw_cursor_t cursor;
837         unw_context_t uc;
838         unsigned i = 0;
839
840         char procname[256];
841         unw_word_t ip, sp, off;
842
843         procname[sizeof(procname) - 1] = '\0';
844
845         if (unw_getcontext(&uc) != 0) {
846                 goto libunwind_failed;
847         }
848
849         if (unw_init_local(&cursor, &uc) != 0) {
850                 goto libunwind_failed;
851         }
852
853         DEBUG(0, ("BACKTRACE:\n"));
854
855         do {
856             ip = sp = 0;
857             unw_get_reg(&cursor, UNW_REG_IP, &ip);
858             unw_get_reg(&cursor, UNW_REG_SP, &sp);
859
860             switch (unw_get_proc_name(&cursor,
861                         procname, sizeof(procname) - 1, &off) ) {
862             case 0:
863                     /* Name found. */
864             case -UNW_ENOMEM:
865                     /* Name truncated. */
866                     DEBUGADD(0, (" #%u %s + %#llx [ip=%#llx] [sp=%#llx]\n",
867                             i, procname, (long long)off,
868                             (long long)ip, (long long) sp));
869                     break;
870             default:
871             /* case -UNW_ENOINFO: */
872             /* case -UNW_EUNSPEC: */
873                     /* No symbol name found. */
874                     DEBUGADD(0, (" #%u %s [ip=%#llx] [sp=%#llx]\n",
875                             i, "<unknown symbol>",
876                             (long long)ip, (long long) sp));
877             }
878             ++i;
879         } while (unw_step(&cursor) > 0);
880
881         return;
882
883 libunwind_failed:
884         DEBUG(0, ("unable to produce a stack trace with libunwind\n"));
885
886 #elif HAVE_BACKTRACE_SYMBOLS
887         void *backtrace_stack[BACKTRACE_STACK_SIZE];
888         size_t backtrace_size;
889         char **backtrace_strings;
890
891         /* get the backtrace (stack frames) */
892         backtrace_size = backtrace(backtrace_stack,BACKTRACE_STACK_SIZE);
893         backtrace_strings = backtrace_symbols(backtrace_stack, backtrace_size);
894
895         DEBUG(0, ("BACKTRACE: %lu stack frames:\n", 
896                   (unsigned long)backtrace_size));
897
898         if (backtrace_strings) {
899                 int i;
900
901                 for (i = 0; i < backtrace_size; i++)
902                         DEBUGADD(0, (" #%u %s\n", i, backtrace_strings[i]));
903
904                 /* Leak the backtrace_strings, rather than risk what free() might do */
905         }
906
907 #elif HAVE_LIBEXC
908
909         /* The IRIX libexc library provides an API for unwinding the stack. See
910          * libexc(3) for details. Apparantly trace_back_stack leaks memory, but
911          * since we are about to abort anyway, it hardly matters.
912          */
913
914 #define NAMESIZE 32 /* Arbitrary */
915
916         __uint64_t      addrs[BACKTRACE_STACK_SIZE];
917         char *          names[BACKTRACE_STACK_SIZE];
918         char            namebuf[BACKTRACE_STACK_SIZE * NAMESIZE];
919
920         int             i;
921         int             levels;
922
923         ZERO_ARRAY(addrs);
924         ZERO_ARRAY(names);
925         ZERO_ARRAY(namebuf);
926
927         /* We need to be root so we can open our /proc entry to walk
928          * our stack. It also helps when we want to dump core.
929          */
930         become_root();
931
932         for (i = 0; i < BACKTRACE_STACK_SIZE; i++) {
933                 names[i] = namebuf + (i * NAMESIZE);
934         }
935
936         levels = trace_back_stack(0, addrs, names,
937                         BACKTRACE_STACK_SIZE, NAMESIZE - 1);
938
939         DEBUG(0, ("BACKTRACE: %d stack frames:\n", levels));
940         for (i = 0; i < levels; i++) {
941                 DEBUGADD(0, (" #%d 0x%llx %s\n", i, addrs[i], names[i]));
942         }
943 #undef NAMESIZE
944
945 #else
946         DEBUG(0, ("unable to produce a stack trace on this platform\n"));
947 #endif
948 }
949
950 /*******************************************************************
951   A readdir wrapper which just returns the file name.
952  ********************************************************************/
953
954 const char *readdirname(DIR *p)
955 {
956         struct dirent *ptr;
957         char *dname;
958
959         if (!p)
960                 return(NULL);
961
962         ptr = (struct dirent *)readdir(p);
963         if (!ptr)
964                 return(NULL);
965
966         dname = ptr->d_name;
967
968 #ifdef NEXT2
969         if (telldir(p) < 0)
970                 return(NULL);
971 #endif
972
973 #ifdef HAVE_BROKEN_READDIR_NAME
974         /* using /usr/ucb/cc is BAD */
975         dname = dname - 2;
976 #endif
977
978         return talloc_strdup(talloc_tos(), dname);
979 }
980
981 /*******************************************************************
982  Utility function used to decide if the last component 
983  of a path matches a (possibly wildcarded) entry in a namelist.
984 ********************************************************************/
985
986 bool is_in_path(const char *name, name_compare_entry *namelist, bool case_sensitive)
987 {
988         const char *last_component;
989
990         /* if we have no list it's obviously not in the path */
991         if((namelist == NULL ) || ((namelist != NULL) && (namelist[0].name == NULL))) {
992                 return False;
993         }
994
995         DEBUG(8, ("is_in_path: %s\n", name));
996
997         /* Get the last component of the unix name. */
998         last_component = strrchr_m(name, '/');
999         if (!last_component) {
1000                 last_component = name;
1001         } else {
1002                 last_component++; /* Go past '/' */
1003         }
1004
1005         for(; namelist->name != NULL; namelist++) {
1006                 if(namelist->is_wild) {
1007                         if (mask_match(last_component, namelist->name, case_sensitive)) {
1008                                 DEBUG(8,("is_in_path: mask match succeeded\n"));
1009                                 return True;
1010                         }
1011                 } else {
1012                         if((case_sensitive && (strcmp(last_component, namelist->name) == 0))||
1013                                                 (!case_sensitive && (strcasecmp_m(last_component, namelist->name) == 0))) {
1014                                 DEBUG(8,("is_in_path: match succeeded\n"));
1015                                 return True;
1016                         }
1017                 }
1018         }
1019         DEBUG(8,("is_in_path: match not found\n"));
1020         return False;
1021 }
1022
1023 /*******************************************************************
1024  Strip a '/' separated list into an array of 
1025  name_compare_enties structures suitable for 
1026  passing to is_in_path(). We do this for
1027  speed so we can pre-parse all the names in the list 
1028  and don't do it for each call to is_in_path().
1029  We also check if the entry contains a wildcard to
1030  remove a potentially expensive call to mask_match
1031  if possible.
1032 ********************************************************************/
1033
1034 void set_namearray(name_compare_entry **ppname_array, const char *namelist_in)
1035 {
1036         char *name_end;
1037         char *namelist;
1038         char *nameptr;
1039         int num_entries = 0;
1040         int i;
1041
1042         (*ppname_array) = NULL;
1043
1044         if((namelist_in == NULL ) || ((namelist_in != NULL) && (*namelist_in == '\0'))) 
1045                 return;
1046
1047         namelist = talloc_strdup(talloc_tos(), namelist_in);
1048         if (namelist == NULL) {
1049                 DEBUG(0,("set_namearray: talloc fail\n"));
1050                 return;
1051         }
1052         nameptr = namelist;
1053
1054         /* We need to make two passes over the string. The
1055                 first to count the number of elements, the second
1056                 to split it.
1057         */
1058
1059         while(*nameptr) {
1060                 if ( *nameptr == '/' ) {
1061                         /* cope with multiple (useless) /s) */
1062                         nameptr++;
1063                         continue;
1064                 }
1065                 /* anything left? */
1066                 if ( *nameptr == '\0' )
1067                         break;
1068
1069                 /* find the next '/' or consume remaining */
1070                 name_end = strchr_m(nameptr, '/');
1071                 if (name_end == NULL)
1072                         name_end = (char *)nameptr + strlen(nameptr);
1073
1074                 /* next segment please */
1075                 nameptr = name_end + 1;
1076                 num_entries++;
1077         }
1078
1079         if(num_entries == 0) {
1080                 talloc_free(namelist);
1081                 return;
1082         }
1083
1084         if(( (*ppname_array) = SMB_MALLOC_ARRAY(name_compare_entry, num_entries + 1)) == NULL) {
1085                 DEBUG(0,("set_namearray: malloc fail\n"));
1086                 talloc_free(namelist);
1087                 return;
1088         }
1089
1090         /* Now copy out the names */
1091         nameptr = namelist;
1092         i = 0;
1093         while(*nameptr) {
1094                 if ( *nameptr == '/' ) {
1095                         /* cope with multiple (useless) /s) */
1096                         nameptr++;
1097                         continue;
1098                 }
1099                 /* anything left? */
1100                 if ( *nameptr == '\0' )
1101                         break;
1102
1103                 /* find the next '/' or consume remaining */
1104                 name_end = strchr_m(nameptr, '/');
1105                 if (name_end)
1106                         *name_end = '\0';
1107                 else
1108                         name_end = nameptr + strlen(nameptr);
1109
1110                 (*ppname_array)[i].is_wild = ms_has_wild(nameptr);
1111                 if(((*ppname_array)[i].name = SMB_STRDUP(nameptr)) == NULL) {
1112                         DEBUG(0,("set_namearray: malloc fail (1)\n"));
1113                         talloc_free(namelist);
1114                         return;
1115                 }
1116
1117                 /* next segment please */
1118                 nameptr = name_end + 1;
1119                 i++;
1120         }
1121
1122         (*ppname_array)[i].name = NULL;
1123
1124         talloc_free(namelist);
1125         return;
1126 }
1127
1128 #undef DBGC_CLASS
1129 #define DBGC_CLASS DBGC_LOCKING
1130
1131 /****************************************************************************
1132  Simple routine to query existing file locks. Cruft in NFS and 64->32 bit mapping
1133  is dealt with in posix.c
1134  Returns True if we have information regarding this lock region (and returns
1135  F_UNLCK in *ptype if the region is unlocked). False if the call failed.
1136 ****************************************************************************/
1137
1138 bool fcntl_getlock(int fd, off_t *poffset, off_t *pcount, int *ptype, pid_t *ppid)
1139 {
1140         struct flock lock;
1141         int ret;
1142
1143         DEBUG(8,("fcntl_getlock fd=%d offset=%.0f count=%.0f type=%d\n",
1144                     fd,(double)*poffset,(double)*pcount,*ptype));
1145
1146         lock.l_type = *ptype;
1147         lock.l_whence = SEEK_SET;
1148         lock.l_start = *poffset;
1149         lock.l_len = *pcount;
1150         lock.l_pid = 0;
1151
1152         ret = sys_fcntl_ptr(fd,F_GETLK,&lock);
1153
1154         if (ret == -1) {
1155                 int sav = errno;
1156                 DEBUG(3,("fcntl_getlock: lock request failed at offset %.0f count %.0f type %d (%s)\n",
1157                         (double)*poffset,(double)*pcount,*ptype,strerror(errno)));
1158                 errno = sav;
1159                 return False;
1160         }
1161
1162         *ptype = lock.l_type;
1163         *poffset = lock.l_start;
1164         *pcount = lock.l_len;
1165         *ppid = lock.l_pid;
1166
1167         DEBUG(3,("fcntl_getlock: fd %d is returned info %d pid %u\n",
1168                         fd, (int)lock.l_type, (unsigned int)lock.l_pid));
1169         return True;
1170 }
1171
1172 #undef DBGC_CLASS
1173 #define DBGC_CLASS DBGC_ALL
1174
1175 /*******************************************************************
1176  Is the name specified one of my netbios names.
1177  Returns true if it is equal, false otherwise.
1178 ********************************************************************/
1179
1180 bool is_myname(const char *s)
1181 {
1182         int n;
1183         bool ret = False;
1184
1185         for (n=0; my_netbios_names(n); n++) {
1186                 if (strequal(my_netbios_names(n), s)) {
1187                         ret=True;
1188                         break;
1189                 }
1190         }
1191         DEBUG(8, ("is_myname(\"%s\") returns %d\n", s, ret));
1192         return(ret);
1193 }
1194
1195 /*******************************************************************
1196  we distinguish between 2K and XP by the "Native Lan Manager" string
1197    WinXP => "Windows 2002 5.1"
1198    WinXP 64bit => "Windows XP 5.2"
1199    Win2k => "Windows 2000 5.0"
1200    NT4   => "Windows NT 4.0"
1201    Win9x => "Windows 4.0"
1202  Windows 2003 doesn't set the native lan manager string but
1203  they do set the domain to "Windows 2003 5.2" (probably a bug).
1204 ********************************************************************/
1205
1206 void ra_lanman_string( const char *native_lanman )
1207 {
1208         if ( strcmp( native_lanman, "Windows 2002 5.1" ) == 0 )
1209                 set_remote_arch( RA_WINXP );
1210         else if ( strcmp( native_lanman, "Windows XP 5.2" ) == 0 )
1211                 set_remote_arch( RA_WINXP64 );
1212         else if ( strcmp( native_lanman, "Windows Server 2003 5.2" ) == 0 )
1213                 set_remote_arch( RA_WIN2K3 );
1214 }
1215
1216 static const char *remote_arch_str;
1217
1218 const char *get_remote_arch_str(void)
1219 {
1220         if (!remote_arch_str) {
1221                 return "UNKNOWN";
1222         }
1223         return remote_arch_str;
1224 }
1225
1226 /*******************************************************************
1227  Set the horrid remote_arch string based on an enum.
1228 ********************************************************************/
1229
1230 void set_remote_arch(enum remote_arch_types type)
1231 {
1232         ra_type = type;
1233         switch( type ) {
1234         case RA_WFWG:
1235                 remote_arch_str = "WfWg";
1236                 break;
1237         case RA_OS2:
1238                 remote_arch_str = "OS2";
1239                 break;
1240         case RA_WIN95:
1241                 remote_arch_str = "Win95";
1242                 break;
1243         case RA_WINNT:
1244                 remote_arch_str = "WinNT";
1245                 break;
1246         case RA_WIN2K:
1247                 remote_arch_str = "Win2K";
1248                 break;
1249         case RA_WINXP:
1250                 remote_arch_str = "WinXP";
1251                 break;
1252         case RA_WINXP64:
1253                 remote_arch_str = "WinXP64";
1254                 break;
1255         case RA_WIN2K3:
1256                 remote_arch_str = "Win2K3";
1257                 break;
1258         case RA_VISTA:
1259                 remote_arch_str = "Vista";
1260                 break;
1261         case RA_SAMBA:
1262                 remote_arch_str = "Samba";
1263                 break;
1264         case RA_CIFSFS:
1265                 remote_arch_str = "CIFSFS";
1266                 break;
1267         case RA_OSX:
1268                 remote_arch_str = "OSX";
1269                 break;
1270         default:
1271                 ra_type = RA_UNKNOWN;
1272                 remote_arch_str = "UNKNOWN";
1273                 break;
1274         }
1275
1276         DEBUG(10,("set_remote_arch: Client arch is \'%s\'\n",
1277                                 remote_arch_str));
1278 }
1279
1280 /*******************************************************************
1281  Get the remote_arch type.
1282 ********************************************************************/
1283
1284 enum remote_arch_types get_remote_arch(void)
1285 {
1286         return ra_type;
1287 }
1288
1289 const char *tab_depth(int level, int depth)
1290 {
1291         if( CHECK_DEBUGLVL(level) ) {
1292                 dbgtext("%*s", depth*4, "");
1293         }
1294         return "";
1295 }
1296
1297 /*****************************************************************************
1298  Provide a checksum on a string
1299
1300  Input:  s - the null-terminated character string for which the checksum
1301              will be calculated.
1302
1303   Output: The checksum value calculated for s.
1304 *****************************************************************************/
1305
1306 int str_checksum(const char *s)
1307 {
1308         if (s == NULL)
1309                 return 0;
1310         return hash(s, strlen(s), 0);
1311 }
1312
1313 /*****************************************************************
1314  Zero a memory area then free it. Used to catch bugs faster.
1315 *****************************************************************/  
1316
1317 void zero_free(void *p, size_t size)
1318 {
1319         memset(p, 0, size);
1320         SAFE_FREE(p);
1321 }
1322
1323 /*****************************************************************
1324  Set our open file limit to a requested max and return the limit.
1325 *****************************************************************/  
1326
1327 int set_maxfiles(int requested_max)
1328 {
1329 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
1330         struct rlimit rlp;
1331         int saved_current_limit;
1332
1333         if(getrlimit(RLIMIT_NOFILE, &rlp)) {
1334                 DEBUG(0,("set_maxfiles: getrlimit (1) for RLIMIT_NOFILE failed with error %s\n",
1335                         strerror(errno) ));
1336                 /* just guess... */
1337                 return requested_max;
1338         }
1339
1340         /* 
1341          * Set the fd limit to be real_max_open_files + MAX_OPEN_FUDGEFACTOR to
1342          * account for the extra fd we need 
1343          * as well as the log files and standard
1344          * handles etc. Save the limit we want to set in case
1345          * we are running on an OS that doesn't support this limit (AIX)
1346          * which always returns RLIM_INFINITY for rlp.rlim_max.
1347          */
1348
1349         /* Try raising the hard (max) limit to the requested amount. */
1350
1351 #if defined(RLIM_INFINITY)
1352         if (rlp.rlim_max != RLIM_INFINITY) {
1353                 int orig_max = rlp.rlim_max;
1354
1355                 if ( rlp.rlim_max < requested_max )
1356                         rlp.rlim_max = requested_max;
1357
1358                 /* This failing is not an error - many systems (Linux) don't
1359                         support our default request of 10,000 open files. JRA. */
1360
1361                 if(setrlimit(RLIMIT_NOFILE, &rlp)) {
1362                         DEBUG(3,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d max files failed with error %s\n", 
1363                                 (int)rlp.rlim_max, strerror(errno) ));
1364
1365                         /* Set failed - restore original value from get. */
1366                         rlp.rlim_max = orig_max;
1367                 }
1368         }
1369 #endif
1370
1371         /* Now try setting the soft (current) limit. */
1372
1373         saved_current_limit = rlp.rlim_cur = MIN(requested_max,rlp.rlim_max);
1374
1375         if(setrlimit(RLIMIT_NOFILE, &rlp)) {
1376                 DEBUG(0,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d files failed with error %s\n", 
1377                         (int)rlp.rlim_cur, strerror(errno) ));
1378                 /* just guess... */
1379                 return saved_current_limit;
1380         }
1381
1382         if(getrlimit(RLIMIT_NOFILE, &rlp)) {
1383                 DEBUG(0,("set_maxfiles: getrlimit (2) for RLIMIT_NOFILE failed with error %s\n",
1384                         strerror(errno) ));
1385                 /* just guess... */
1386                 return saved_current_limit;
1387     }
1388
1389 #if defined(RLIM_INFINITY)
1390         if(rlp.rlim_cur == RLIM_INFINITY)
1391                 return saved_current_limit;
1392 #endif
1393
1394         if((int)rlp.rlim_cur > saved_current_limit)
1395                 return saved_current_limit;
1396
1397         return rlp.rlim_cur;
1398 #else /* !defined(HAVE_GETRLIMIT) || !defined(RLIMIT_NOFILE) */
1399         /*
1400          * No way to know - just guess...
1401          */
1402         return requested_max;
1403 #endif
1404 }
1405
1406 /*****************************************************************
1407  malloc that aborts with smb_panic on fail or zero size.
1408  *****************************************************************/  
1409
1410 void *smb_xmalloc_array(size_t size, unsigned int count)
1411 {
1412         void *p;
1413         if (size == 0) {
1414                 smb_panic("smb_xmalloc_array: called with zero size");
1415         }
1416         if (count >= MAX_ALLOC_SIZE/size) {
1417                 smb_panic("smb_xmalloc_array: alloc size too large");
1418         }
1419         if ((p = SMB_MALLOC(size*count)) == NULL) {
1420                 DEBUG(0, ("smb_xmalloc_array failed to allocate %lu * %lu bytes\n",
1421                         (unsigned long)size, (unsigned long)count));
1422                 smb_panic("smb_xmalloc_array: malloc failed");
1423         }
1424         return p;
1425 }
1426
1427 /*
1428   vasprintf that aborts on malloc fail
1429 */
1430
1431  int smb_xvasprintf(char **ptr, const char *format, va_list ap)
1432 {
1433         int n;
1434         va_list ap2;
1435
1436         va_copy(ap2, ap);
1437
1438         n = vasprintf(ptr, format, ap2);
1439         va_end(ap2);
1440         if (n == -1 || ! *ptr) {
1441                 smb_panic("smb_xvasprintf: out of memory");
1442         }
1443         return n;
1444 }
1445
1446 /*****************************************************************
1447  Get local hostname and cache result.
1448 *****************************************************************/
1449
1450 char *myhostname(void)
1451 {
1452         static char *ret;
1453         if (ret == NULL) {
1454                 ret = get_myname(NULL);
1455         }
1456         return ret;
1457 }
1458
1459 /*****************************************************************
1460  Get local hostname and cache result.
1461 *****************************************************************/
1462
1463 char *myhostname_upper(void)
1464 {
1465         static char *ret;
1466         if (ret == NULL) {
1467                 char *name = get_myname(NULL);
1468                 if (name == NULL) {
1469                         return NULL;
1470                 }
1471                 ret = strupper_talloc(NULL, name);
1472                 talloc_free(name);
1473         }
1474         return ret;
1475 }
1476
1477 /**
1478  * @brief Returns an absolute path to a file concatenating the provided
1479  * @a rootpath and @a basename
1480  *
1481  * @param name Filename, relative to @a rootpath
1482  *
1483  * @retval Pointer to a string containing the full path.
1484  **/
1485
1486 static char *xx_path(const char *name, const char *rootpath)
1487 {
1488         char *fname = NULL;
1489
1490         fname = talloc_strdup(talloc_tos(), rootpath);
1491         if (!fname) {
1492                 return NULL;
1493         }
1494         trim_string(fname,"","/");
1495
1496         if (!directory_exist(fname)) {
1497                 if (mkdir(fname,0755) == -1) {
1498                         /* Did someone else win the race ? */
1499                         if (errno != EEXIST) {
1500                                 DEBUG(1, ("Unable to create directory %s for file %s. "
1501                                         "Error was %s\n", fname, name, strerror(errno)));
1502                                 return NULL;
1503                         }
1504                 }
1505         }
1506
1507         return talloc_asprintf_append(fname, "/%s", name);
1508 }
1509
1510 /**
1511  * @brief Returns an absolute path to a file in the Samba lock directory.
1512  *
1513  * @param name File to find, relative to LOCKDIR.
1514  *
1515  * @retval Pointer to a talloc'ed string containing the full path.
1516  **/
1517
1518 char *lock_path(const char *name)
1519 {
1520         return xx_path(name, lp_lock_directory());
1521 }
1522
1523 /**
1524  * @brief Returns an absolute path to a file in the Samba state directory.
1525  *
1526  * @param name File to find, relative to STATEDIR.
1527  *
1528  * @retval Pointer to a talloc'ed string containing the full path.
1529  **/
1530
1531 char *state_path(const char *name)
1532 {
1533         return xx_path(name, lp_statedir());
1534 }
1535
1536 /**
1537  * @brief Returns an absolute path to a file in the Samba cache directory.
1538  *
1539  * @param name File to find, relative to CACHEDIR.
1540  *
1541  * @retval Pointer to a talloc'ed string containing the full path.
1542  **/
1543
1544 char *cache_path(const char *name)
1545 {
1546         return xx_path(name, lp_cachedir());
1547 }
1548
1549 /*******************************************************************
1550  Given a filename - get its directory name
1551 ********************************************************************/
1552
1553 bool parent_dirname(TALLOC_CTX *mem_ctx, const char *dir, char **parent,
1554                     const char **name)
1555 {
1556         char *p;
1557         ptrdiff_t len;
1558
1559         p = strrchr_m(dir, '/'); /* Find final '/', if any */
1560
1561         if (p == NULL) {
1562                 if (!(*parent = talloc_strdup(mem_ctx, "."))) {
1563                         return False;
1564                 }
1565                 if (name) {
1566                         *name = dir;
1567                 }
1568                 return True;
1569         }
1570
1571         len = p-dir;
1572
1573         if (!(*parent = (char *)talloc_memdup(mem_ctx, dir, len+1))) {
1574                 return False;
1575         }
1576         (*parent)[len] = '\0';
1577
1578         if (name) {
1579                 *name = p+1;
1580         }
1581         return True;
1582 }
1583
1584 /*******************************************************************
1585  Determine if a pattern contains any Microsoft wildcard characters.
1586 *******************************************************************/
1587
1588 bool ms_has_wild(const char *s)
1589 {
1590         char c;
1591
1592         if (lp_posix_pathnames()) {
1593                 /* With posix pathnames no characters are wild. */
1594                 return False;
1595         }
1596
1597         while ((c = *s++)) {
1598                 switch (c) {
1599                 case '*':
1600                 case '?':
1601                 case '<':
1602                 case '>':
1603                 case '"':
1604                         return True;
1605                 }
1606         }
1607         return False;
1608 }
1609
1610 bool ms_has_wild_w(const smb_ucs2_t *s)
1611 {
1612         smb_ucs2_t c;
1613         if (!s) return False;
1614         while ((c = *s++)) {
1615                 switch (c) {
1616                 case UCS2_CHAR('*'):
1617                 case UCS2_CHAR('?'):
1618                 case UCS2_CHAR('<'):
1619                 case UCS2_CHAR('>'):
1620                 case UCS2_CHAR('"'):
1621                         return True;
1622                 }
1623         }
1624         return False;
1625 }
1626
1627 /*******************************************************************
1628  A wrapper that handles case sensitivity and the special handling
1629  of the ".." name.
1630 *******************************************************************/
1631
1632 bool mask_match(const char *string, const char *pattern, bool is_case_sensitive)
1633 {
1634         if (ISDOTDOT(string))
1635                 string = ".";
1636         if (ISDOT(pattern))
1637                 return False;
1638
1639         return ms_fnmatch(pattern, string, Protocol <= PROTOCOL_LANMAN2, is_case_sensitive) == 0;
1640 }
1641
1642 /*******************************************************************
1643  A wrapper that handles case sensitivity and the special handling
1644  of the ".." name. Varient that is only called by old search code which requires
1645  pattern translation.
1646 *******************************************************************/
1647
1648 bool mask_match_search(const char *string, const char *pattern, bool is_case_sensitive)
1649 {
1650         if (ISDOTDOT(string))
1651                 string = ".";
1652         if (ISDOT(pattern))
1653                 return False;
1654
1655         return ms_fnmatch(pattern, string, True, is_case_sensitive) == 0;
1656 }
1657
1658 /*******************************************************************
1659  A wrapper that handles a list of patters and calls mask_match()
1660  on each.  Returns True if any of the patterns match.
1661 *******************************************************************/
1662
1663 bool mask_match_list(const char *string, char **list, int listLen, bool is_case_sensitive)
1664 {
1665        while (listLen-- > 0) {
1666                if (mask_match(string, *list++, is_case_sensitive))
1667                        return True;
1668        }
1669        return False;
1670 }
1671
1672 /*********************************************************
1673  Recursive routine that is called by unix_wild_match.
1674 *********************************************************/
1675
1676 static bool unix_do_match(const char *regexp, const char *str)
1677 {
1678         const char *p;
1679
1680         for( p = regexp; *p && *str; ) {
1681
1682                 switch(*p) {
1683                         case '?':
1684                                 str++;
1685                                 p++;
1686                                 break;
1687
1688                         case '*':
1689
1690                                 /*
1691                                  * Look for a character matching 
1692                                  * the one after the '*'.
1693                                  */
1694                                 p++;
1695                                 if(!*p)
1696                                         return true; /* Automatic match */
1697                                 while(*str) {
1698
1699                                         while(*str && (*p != *str))
1700                                                 str++;
1701
1702                                         /*
1703                                          * Patch from weidel@multichart.de. In the case of the regexp
1704                                          * '*XX*' we want to ensure there are at least 2 'X' characters
1705                                          * in the string after the '*' for a match to be made.
1706                                          */
1707
1708                                         {
1709                                                 int matchcount=0;
1710
1711                                                 /*
1712                                                  * Eat all the characters that match, but count how many there were.
1713                                                  */
1714
1715                                                 while(*str && (*p == *str)) {
1716                                                         str++;
1717                                                         matchcount++;
1718                                                 }
1719
1720                                                 /*
1721                                                  * Now check that if the regexp had n identical characters that
1722                                                  * matchcount had at least that many matches.
1723                                                  */
1724
1725                                                 while ( *(p+1) && (*(p+1) == *p)) {
1726                                                         p++;
1727                                                         matchcount--;
1728                                                 }
1729
1730                                                 if ( matchcount <= 0 )
1731                                                         return false;
1732                                         }
1733
1734                                         str--; /* We've eaten the match char after the '*' */
1735
1736                                         if(unix_do_match(p, str))
1737                                                 return true;
1738
1739                                         if(!*str)
1740                                                 return false;
1741                                         else
1742                                                 str++;
1743                                 }
1744                                 return false;
1745
1746                         default:
1747                                 if(*str != *p)
1748                                         return false;
1749                                 str++;
1750                                 p++;
1751                                 break;
1752                 }
1753         }
1754
1755         if(!*p && !*str)
1756                 return true;
1757
1758         if (!*p && str[0] == '.' && str[1] == 0)
1759                 return true;
1760
1761         if (!*str && *p == '?') {
1762                 while (*p == '?')
1763                         p++;
1764                 return(!*p);
1765         }
1766
1767         if(!*str && (*p == '*' && p[1] == '\0'))
1768                 return true;
1769
1770         return false;
1771 }
1772
1773 /*******************************************************************
1774  Simple case insensitive interface to a UNIX wildcard matcher.
1775  Returns True if match, False if not.
1776 *******************************************************************/
1777
1778 bool unix_wild_match(const char *pattern, const char *string)
1779 {
1780         TALLOC_CTX *ctx = talloc_stackframe();
1781         char *p2;
1782         char *s2;
1783         char *p;
1784         bool ret = false;
1785
1786         p2 = talloc_strdup(ctx,pattern);
1787         s2 = talloc_strdup(ctx,string);
1788         if (!p2 || !s2) {
1789                 TALLOC_FREE(ctx);
1790                 return false;
1791         }
1792         if (!strlower_m(p2)) {
1793                 TALLOC_FREE(ctx);
1794                 return false;
1795         }
1796         if (!strlower_m(s2)) {
1797                 TALLOC_FREE(ctx);
1798                 return false;
1799         }
1800
1801         /* Remove any *? and ** from the pattern as they are meaningless */
1802         for(p = p2; *p; p++) {
1803                 while( *p == '*' && (p[1] == '?' ||p[1] == '*')) {
1804                         memmove(&p[1], &p[2], strlen(&p[2])+1);
1805                 }
1806         }
1807
1808         if (strequal(p2,"*")) {
1809                 TALLOC_FREE(ctx);
1810                 return true;
1811         }
1812
1813         ret = unix_do_match(p2, s2);
1814         TALLOC_FREE(ctx);
1815         return ret;
1816 }
1817
1818 /**********************************************************************
1819  Converts a name to a fully qualified domain name.
1820  Returns true if lookup succeeded, false if not (then fqdn is set to name)
1821  Note we deliberately use gethostbyname here, not getaddrinfo as we want
1822  to examine the h_aliases and I don't know how to do that with getaddrinfo.
1823 ***********************************************************************/
1824
1825 bool name_to_fqdn(fstring fqdn, const char *name)
1826 {
1827         char *full = NULL;
1828         struct hostent *hp = gethostbyname(name);
1829
1830         if (!hp || !hp->h_name || !*hp->h_name) {
1831                 DEBUG(10,("name_to_fqdn: lookup for %s failed.\n", name));
1832                 fstrcpy(fqdn, name);
1833                 return false;
1834         }
1835
1836         /* Find out if the fqdn is returned as an alias
1837          * to cope with /etc/hosts files where the first
1838          * name is not the fqdn but the short name */
1839         if (hp->h_aliases && (! strchr_m(hp->h_name, '.'))) {
1840                 int i;
1841                 for (i = 0; hp->h_aliases[i]; i++) {
1842                         if (strchr_m(hp->h_aliases[i], '.')) {
1843                                 full = hp->h_aliases[i];
1844                                 break;
1845                         }
1846                 }
1847         }
1848         if (full && (strcasecmp_m(full, "localhost.localdomain") == 0)) {
1849                 DEBUG(1, ("WARNING: your /etc/hosts file may be broken!\n"));
1850                 DEBUGADD(1, ("    Specifing the machine hostname for address 127.0.0.1 may lead\n"));
1851                 DEBUGADD(1, ("    to Kerberos authentication problems as localhost.localdomain\n"));
1852                 DEBUGADD(1, ("    may end up being used instead of the real machine FQDN.\n"));
1853                 full = hp->h_name;
1854         }
1855         if (!full) {
1856                 full = hp->h_name;
1857         }
1858
1859         DEBUG(10,("name_to_fqdn: lookup for %s -> %s.\n", name, full));
1860         fstrcpy(fqdn, full);
1861         return true;
1862 }
1863
1864 /**********************************************************************
1865  Append a DATA_BLOB to a talloc'ed object
1866 ***********************************************************************/
1867
1868 void *talloc_append_blob(TALLOC_CTX *mem_ctx, void *buf, DATA_BLOB blob)
1869 {
1870         size_t old_size = 0;
1871         char *result;
1872
1873         if (blob.length == 0) {
1874                 return buf;
1875         }
1876
1877         if (buf != NULL) {
1878                 old_size = talloc_get_size(buf);
1879         }
1880
1881         result = (char *)TALLOC_REALLOC(mem_ctx, buf, old_size + blob.length);
1882         if (result == NULL) {
1883                 return NULL;
1884         }
1885
1886         memcpy(result + old_size, blob.data, blob.length);
1887         return result;
1888 }
1889
1890 uint32 map_share_mode_to_deny_mode(uint32 share_access, uint32 private_options)
1891 {
1892         switch (share_access & ~FILE_SHARE_DELETE) {
1893                 case FILE_SHARE_NONE:
1894                         return DENY_ALL;
1895                 case FILE_SHARE_READ:
1896                         return DENY_WRITE;
1897                 case FILE_SHARE_WRITE:
1898                         return DENY_READ;
1899                 case FILE_SHARE_READ|FILE_SHARE_WRITE:
1900                         return DENY_NONE;
1901         }
1902         if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS) {
1903                 return DENY_DOS;
1904         } else if (private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_FCB) {
1905                 return DENY_FCB;
1906         }
1907
1908         return (uint32)-1;
1909 }
1910
1911 pid_t procid_to_pid(const struct server_id *proc)
1912 {
1913         return proc->pid;
1914 }
1915
1916 static uint32 my_vnn = NONCLUSTER_VNN;
1917
1918 void set_my_vnn(uint32 vnn)
1919 {
1920         DEBUG(10, ("vnn pid %d = %u\n", (int)getpid(), (unsigned int)vnn));
1921         my_vnn = vnn;
1922 }
1923
1924 uint32 get_my_vnn(void)
1925 {
1926         return my_vnn;
1927 }
1928
1929 static uint64_t my_unique_id = 0;
1930
1931 void set_my_unique_id(uint64_t unique_id)
1932 {
1933         my_unique_id = unique_id;
1934 }
1935
1936 struct server_id pid_to_procid(pid_t pid)
1937 {
1938         struct server_id result;
1939         result.pid = pid;
1940         result.task_id = 0;
1941         result.unique_id = my_unique_id;
1942         result.vnn = my_vnn;
1943         return result;
1944 }
1945
1946 struct server_id procid_self(void)
1947 {
1948         return pid_to_procid(getpid());
1949 }
1950
1951 static struct idr_context *task_id_tree;
1952
1953 static int free_task_id(struct server_id *server_id)
1954 {
1955         idr_remove(task_id_tree, server_id->task_id);
1956         return 0;
1957 }
1958
1959 /* Return a server_id with a unique task_id element.  Free the
1960  * returned pointer to de-allocate the task_id via a talloc destructor
1961  * (ie, use talloc_free()) */
1962 struct server_id *new_server_id_task(TALLOC_CTX *mem_ctx)
1963 {
1964         struct server_id *server_id;
1965         int task_id;
1966         if (!task_id_tree) {
1967                 task_id_tree = idr_init(NULL);
1968                 if (!task_id_tree) {
1969                         return NULL;
1970                 }
1971         }
1972
1973         server_id = talloc(mem_ctx, struct server_id);
1974
1975         if (!server_id) {
1976                 return NULL;
1977         }
1978         *server_id = procid_self();
1979
1980         /* 0 is the default server_id, so we need to start with 1 */
1981         task_id = idr_get_new_above(task_id_tree, server_id, 1, INT32_MAX);
1982
1983         if (task_id == -1) {
1984                 talloc_free(server_id);
1985                 return NULL;
1986         }
1987
1988         talloc_set_destructor(server_id, free_task_id);
1989         server_id->task_id = task_id;
1990         return server_id;
1991 }
1992
1993 bool procid_is_me(const struct server_id *pid)
1994 {
1995         if (pid->pid != getpid())
1996                 return False;
1997         if (pid->task_id != 0)
1998                 return False;
1999         if (pid->vnn != my_vnn)
2000                 return False;
2001         return True;
2002 }
2003
2004 struct server_id interpret_pid(const char *pid_string)
2005 {
2006         return server_id_from_string(get_my_vnn(), pid_string);
2007 }
2008
2009 char *procid_str_static(const struct server_id *pid)
2010 {
2011         return server_id_str(talloc_tos(), pid);
2012 }
2013
2014 bool procid_valid(const struct server_id *pid)
2015 {
2016         return (pid->pid != (uint64_t)-1);
2017 }
2018
2019 bool procid_is_local(const struct server_id *pid)
2020 {
2021         return pid->vnn == my_vnn;
2022 }
2023
2024 /****************************************************************
2025  Check if an offset into a buffer is safe.
2026  If this returns True it's safe to indirect into the byte at
2027  pointer ptr+off.
2028 ****************************************************************/
2029
2030 bool is_offset_safe(const char *buf_base, size_t buf_len, char *ptr, size_t off)
2031 {
2032         const char *end_base = buf_base + buf_len;
2033         char *end_ptr = ptr + off;
2034
2035         if (!buf_base || !ptr) {
2036                 return False;
2037         }
2038
2039         if (end_base < buf_base || end_ptr < ptr) {
2040                 return False; /* wrap. */
2041         }
2042
2043         if (end_ptr < end_base) {
2044                 return True;
2045         }
2046         return False;
2047 }
2048
2049 /****************************************************************
2050  Return a safe pointer into a buffer, or NULL.
2051 ****************************************************************/
2052
2053 char *get_safe_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
2054 {
2055         return is_offset_safe(buf_base, buf_len, ptr, off) ?
2056                         ptr + off : NULL;
2057 }
2058
2059 /****************************************************************
2060  Return a safe pointer into a string within a buffer, or NULL.
2061 ****************************************************************/
2062
2063 char *get_safe_str_ptr(const char *buf_base, size_t buf_len, char *ptr, size_t off)
2064 {
2065         if (!is_offset_safe(buf_base, buf_len, ptr, off)) {
2066                 return NULL;
2067         }
2068         /* Check if a valid string exists at this offset. */
2069         if (skip_string(buf_base,buf_len, ptr + off) == NULL) {
2070                 return NULL;
2071         }
2072         return ptr + off;
2073 }
2074
2075 /****************************************************************
2076  Return an SVAL at a pointer, or failval if beyond the end.
2077 ****************************************************************/
2078
2079 int get_safe_SVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
2080 {
2081         /*
2082          * Note we use off+1 here, not off+2 as SVAL accesses ptr[0] and ptr[1],
2083          * NOT ptr[2].
2084          */
2085         if (!is_offset_safe(buf_base, buf_len, ptr, off+1)) {
2086                 return failval;
2087         }
2088         return SVAL(ptr,off);
2089 }
2090
2091 /****************************************************************
2092  Return an IVAL at a pointer, or failval if beyond the end.
2093 ****************************************************************/
2094
2095 int get_safe_IVAL(const char *buf_base, size_t buf_len, char *ptr, size_t off, int failval)
2096 {
2097         /*
2098          * Note we use off+3 here, not off+4 as IVAL accesses 
2099          * ptr[0] ptr[1] ptr[2] ptr[3] NOT ptr[4].
2100          */
2101         if (!is_offset_safe(buf_base, buf_len, ptr, off+3)) {
2102                 return failval;
2103         }
2104         return IVAL(ptr,off);
2105 }
2106
2107 /****************************************************************
2108  Split DOM\user into DOM and user. Do not mix with winbind variants of that
2109  call (they take care of winbind separator and other winbind specific settings).
2110 ****************************************************************/
2111
2112 void split_domain_user(TALLOC_CTX *mem_ctx,
2113                        const char *full_name,
2114                        char **domain,
2115                        char **user)
2116 {
2117         const char *p = NULL;
2118
2119         p = strchr_m(full_name, '\\');
2120
2121         if (p != NULL) {
2122                 *domain = talloc_strndup(mem_ctx, full_name,
2123                                          PTR_DIFF(p, full_name));
2124                 *user = talloc_strdup(mem_ctx, p+1);
2125         } else {
2126                 *domain = talloc_strdup(mem_ctx, "");
2127                 *user = talloc_strdup(mem_ctx, full_name);
2128         }
2129 }
2130
2131 /****************************************************************
2132  strip off leading '\\' from a hostname
2133 ****************************************************************/
2134
2135 const char *strip_hostname(const char *s)
2136 {
2137         if (!s) {
2138                 return NULL;
2139         }
2140
2141         if (strlen_m(s) < 3) {
2142                 return s;
2143         }
2144
2145         if (s[0] == '\\') s++;
2146         if (s[0] == '\\') s++;
2147
2148         return s;
2149 }
2150
2151 bool any_nt_status_not_ok(NTSTATUS err1, NTSTATUS err2, NTSTATUS *result)
2152 {
2153         if (!NT_STATUS_IS_OK(err1)) {
2154                 *result = err1;
2155                 return true;
2156         }
2157         if (!NT_STATUS_IS_OK(err2)) {
2158                 *result = err2;
2159                 return true;
2160         }
2161         return false;
2162 }
2163
2164 int timeval_to_msec(struct timeval t)
2165 {
2166         return t.tv_sec * 1000 + (t.tv_usec+999) / 1000;
2167 }
2168
2169 /*******************************************************************
2170  Check a given DOS pathname is valid for a share.
2171 ********************************************************************/
2172
2173 char *valid_share_pathname(TALLOC_CTX *ctx, const char *dos_pathname)
2174 {
2175         char *ptr = NULL;
2176
2177         if (!dos_pathname) {
2178                 return NULL;
2179         }
2180
2181         ptr = talloc_strdup(ctx, dos_pathname);
2182         if (!ptr) {
2183                 return NULL;
2184         }
2185         /* Convert any '\' paths to '/' */
2186         unix_format(ptr);
2187         ptr = unix_clean_name(ctx, ptr);
2188         if (!ptr) {
2189                 return NULL;
2190         }
2191
2192         /* NT is braindead - it wants a C: prefix to a pathname ! So strip it. */
2193         if (strlen(ptr) > 2 && ptr[1] == ':' && ptr[0] != '/')
2194                 ptr += 2;
2195
2196         /* Only absolute paths allowed. */
2197         if (*ptr != '/')
2198                 return NULL;
2199
2200         return ptr;
2201 }
2202
2203 /*******************************************************************
2204  Return True if the filename is one of the special executable types.
2205 ********************************************************************/
2206
2207 bool is_executable(const char *fname)
2208 {
2209         if ((fname = strrchr_m(fname,'.'))) {
2210                 if (strequal(fname,".com") ||
2211                     strequal(fname,".dll") ||
2212                     strequal(fname,".exe") ||
2213                     strequal(fname,".sym")) {
2214                         return True;
2215                 }
2216         }
2217         return False;
2218 }
2219
2220 /****************************************************************************
2221  Open a file with a share mode - old openX method - map into NTCreate.
2222 ****************************************************************************/
2223
2224 bool map_open_params_to_ntcreate(const char *smb_base_fname,
2225                                  int deny_mode, int open_func,
2226                                  uint32 *paccess_mask,
2227                                  uint32 *pshare_mode,
2228                                  uint32 *pcreate_disposition,
2229                                  uint32 *pcreate_options,
2230                                  uint32_t *pprivate_flags)
2231 {
2232         uint32 access_mask;
2233         uint32 share_mode;
2234         uint32 create_disposition;
2235         uint32 create_options = FILE_NON_DIRECTORY_FILE;
2236         uint32_t private_flags = 0;
2237
2238         DEBUG(10,("map_open_params_to_ntcreate: fname = %s, deny_mode = 0x%x, "
2239                   "open_func = 0x%x\n",
2240                   smb_base_fname, (unsigned int)deny_mode,
2241                   (unsigned int)open_func ));
2242
2243         /* Create the NT compatible access_mask. */
2244         switch (GET_OPENX_MODE(deny_mode)) {
2245                 case DOS_OPEN_EXEC: /* Implies read-only - used to be FILE_READ_DATA */
2246                 case DOS_OPEN_RDONLY:
2247                         access_mask = FILE_GENERIC_READ;
2248                         break;
2249                 case DOS_OPEN_WRONLY:
2250                         access_mask = FILE_GENERIC_WRITE;
2251                         break;
2252                 case DOS_OPEN_RDWR:
2253                 case DOS_OPEN_FCB:
2254                         access_mask = FILE_GENERIC_READ|FILE_GENERIC_WRITE;
2255                         break;
2256                 default:
2257                         DEBUG(10,("map_open_params_to_ntcreate: bad open mode = 0x%x\n",
2258                                   (unsigned int)GET_OPENX_MODE(deny_mode)));
2259                         return False;
2260         }
2261
2262         /* Create the NT compatible create_disposition. */
2263         switch (open_func) {
2264                 case OPENX_FILE_EXISTS_FAIL|OPENX_FILE_CREATE_IF_NOT_EXIST:
2265                         create_disposition = FILE_CREATE;
2266                         break;
2267
2268                 case OPENX_FILE_EXISTS_OPEN:
2269                         create_disposition = FILE_OPEN;
2270                         break;
2271
2272                 case OPENX_FILE_EXISTS_OPEN|OPENX_FILE_CREATE_IF_NOT_EXIST:
2273                         create_disposition = FILE_OPEN_IF;
2274                         break;
2275
2276                 case OPENX_FILE_EXISTS_TRUNCATE:
2277                         create_disposition = FILE_OVERWRITE;
2278                         break;
2279
2280                 case OPENX_FILE_EXISTS_TRUNCATE|OPENX_FILE_CREATE_IF_NOT_EXIST:
2281                         create_disposition = FILE_OVERWRITE_IF;
2282                         break;
2283
2284                 default:
2285                         /* From samba4 - to be confirmed. */
2286                         if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_EXEC) {
2287                                 create_disposition = FILE_CREATE;
2288                                 break;
2289                         }
2290                         DEBUG(10,("map_open_params_to_ntcreate: bad "
2291                                   "open_func 0x%x\n", (unsigned int)open_func));
2292                         return False;
2293         }
2294
2295         /* Create the NT compatible share modes. */
2296         switch (GET_DENY_MODE(deny_mode)) {
2297                 case DENY_ALL:
2298                         share_mode = FILE_SHARE_NONE;
2299                         break;
2300
2301                 case DENY_WRITE:
2302                         share_mode = FILE_SHARE_READ;
2303                         break;
2304
2305                 case DENY_READ:
2306                         share_mode = FILE_SHARE_WRITE;
2307                         break;
2308
2309                 case DENY_NONE:
2310                         share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2311                         break;
2312
2313                 case DENY_DOS:
2314                         private_flags |= NTCREATEX_OPTIONS_PRIVATE_DENY_DOS;
2315                         if (is_executable(smb_base_fname)) {
2316                                 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2317                         } else {
2318                                 if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_RDONLY) {
2319                                         share_mode = FILE_SHARE_READ;
2320                                 } else {
2321                                         share_mode = FILE_SHARE_NONE;
2322                                 }
2323                         }
2324                         break;
2325
2326                 case DENY_FCB:
2327                         private_flags |= NTCREATEX_OPTIONS_PRIVATE_DENY_FCB;
2328                         share_mode = FILE_SHARE_NONE;
2329                         break;
2330
2331                 default:
2332                         DEBUG(10,("map_open_params_to_ntcreate: bad deny_mode 0x%x\n",
2333                                 (unsigned int)GET_DENY_MODE(deny_mode) ));
2334                         return False;
2335         }
2336
2337         DEBUG(10,("map_open_params_to_ntcreate: file %s, access_mask = 0x%x, "
2338                   "share_mode = 0x%x, create_disposition = 0x%x, "
2339                   "create_options = 0x%x private_flags = 0x%x\n",
2340                   smb_base_fname,
2341                   (unsigned int)access_mask,
2342                   (unsigned int)share_mode,
2343                   (unsigned int)create_disposition,
2344                   (unsigned int)create_options,
2345                   (unsigned int)private_flags));
2346
2347         if (paccess_mask) {
2348                 *paccess_mask = access_mask;
2349         }
2350         if (pshare_mode) {
2351                 *pshare_mode = share_mode;
2352         }
2353         if (pcreate_disposition) {
2354                 *pcreate_disposition = create_disposition;
2355         }
2356         if (pcreate_options) {
2357                 *pcreate_options = create_options;
2358         }
2359         if (pprivate_flags) {
2360                 *pprivate_flags = private_flags;
2361         }
2362
2363         return True;
2364
2365 }
2366
2367 /*************************************************************************
2368  Return a talloced copy of a struct security_unix_token. NULL on fail.
2369 *************************************************************************/
2370
2371 struct security_unix_token *copy_unix_token(TALLOC_CTX *ctx, const struct security_unix_token *tok)
2372 {
2373         struct security_unix_token *cpy;
2374
2375         cpy = talloc(ctx, struct security_unix_token);
2376         if (!cpy) {
2377                 return NULL;
2378         }
2379
2380         cpy->uid = tok->uid;
2381         cpy->gid = tok->gid;
2382         cpy->ngroups = tok->ngroups;
2383         if (tok->ngroups) {
2384                 /* Make this a talloc child of cpy. */
2385                 cpy->groups = (gid_t *)talloc_memdup(
2386                         cpy, tok->groups, tok->ngroups * sizeof(gid_t));
2387                 if (!cpy->groups) {
2388                         TALLOC_FREE(cpy);
2389                         return NULL;
2390                 }
2391         } else {
2392                 cpy->groups = NULL;
2393         }
2394         return cpy;
2395 }
2396
2397 /****************************************************************************
2398  Check that a file matches a particular file type.
2399 ****************************************************************************/
2400
2401 bool dir_check_ftype(uint32_t mode, uint32_t dirtype)
2402 {
2403         uint32_t mask;
2404
2405         /* Check the "may have" search bits. */
2406         if (((mode & ~dirtype) &
2407                         (FILE_ATTRIBUTE_HIDDEN |
2408                          FILE_ATTRIBUTE_SYSTEM |
2409                          FILE_ATTRIBUTE_DIRECTORY)) != 0) {
2410                 return false;
2411         }
2412
2413         /* Check the "must have" bits,
2414            which are the may have bits shifted eight */
2415         /* If must have bit is set, the file/dir can
2416            not be returned in search unless the matching
2417            file attribute is set */
2418         mask = ((dirtype >> 8) & (FILE_ATTRIBUTE_DIRECTORY|
2419                                     FILE_ATTRIBUTE_ARCHIVE|
2420                                    FILE_ATTRIBUTE_READONLY|
2421                                      FILE_ATTRIBUTE_HIDDEN|
2422                                      FILE_ATTRIBUTE_SYSTEM)); /* & 0x37 */
2423         if(mask) {
2424                 if((mask & (mode & (FILE_ATTRIBUTE_DIRECTORY|
2425                                       FILE_ATTRIBUTE_ARCHIVE|
2426                                      FILE_ATTRIBUTE_READONLY|
2427                                        FILE_ATTRIBUTE_HIDDEN|
2428                                         FILE_ATTRIBUTE_SYSTEM))) == mask) {
2429                         /* check if matching attribute present */
2430                         return true;
2431                 } else {
2432                         return false;
2433                 }
2434         }
2435
2436         return true;
2437 }