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