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