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