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