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