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