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