Ticket 1551: Update GPL version from 2 to 3
[midnight-commander.git] / src / vfs / smbfs / helpers / lib / util.c
blob939cdc0184518b50bf27225e7bced1b4baa2dec4
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 Samba utility functions
6 Copyright (C) Andrew Tridgell 1992-1998
8 Copyright (C) 2011
9 The Free Software Foundation, Inc.
11 This file is part of the Midnight Commander.
13 The Midnight Commander is free software: you can redistribute it
14 and/or modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation, either version 3 of the License,
16 or (at your option) any later version.
18 The Midnight Commander is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 #include "includes.h"
29 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
30 #ifdef WITH_NISPLUS_HOME
31 #ifdef BROKEN_NISPLUS_INCLUDE_FILES
33 * The following lines are needed due to buggy include files
34 * in Solaris 2.6 which define GROUP in both /usr/include/sys/acl.h and
35 * also in /usr/include/rpcsvc/nis.h. The definitions conflict. JRA.
36 * Also GROUP_OBJ is defined as 0x4 in /usr/include/sys/acl.h and as
37 * an enum in /usr/include/rpcsvc/nis.h.
40 #if defined(GROUP)
41 #undef GROUP
42 #endif
44 #if defined(GROUP_OBJ)
45 #undef GROUP_OBJ
46 #endif
48 #endif /* BROKEN_NISPLUS_INCLUDE_FILES */
50 #include <rpcsvc/nis.h>
52 #else /* !WITH_NISPLUS_HOME */
54 #include "rpcsvc/ypclnt.h"
56 #endif /* WITH_NISPLUS_HOME */
57 #endif /* HAVE_NETGROUP && WITH_AUTOMOUNT */
59 #ifdef WITH_SSL
60 #include <ssl.h>
61 #undef Realloc /* SSLeay defines this and samba has a function of this name */
62 extern SSL *ssl;
63 extern int sslFd;
64 #endif /* WITH_SSL */
66 extern int DEBUGLEVEL;
67 #if 0
68 int Protocol = PROTOCOL_COREPLUS;
69 #endif /*0 */
71 /* a default finfo structure to ensure all fields are sensible */
72 file_info const def_finfo = { -1, 0, 0, 0, 0, 0, 0, "" };
74 /* the client file descriptor */
75 extern int Client;
77 /* this is used by the chaining code */
78 const int chain_size = 0;
79 #if 0
80 int trans_num = 0;
81 #endif /*0 */
84 case handling on filenames
86 const int case_default = CASE_LOWER;
88 #if 0
89 /* the following control case operations - they are put here so the
90 client can link easily */
91 BOOL case_sensitive;
92 BOOL case_preserve;
93 BOOL use_mangled_map = False;
94 BOOL short_case_preserve;
95 BOOL case_mangle;
96 #endif /*0 */
98 static const char *remote_machine = "";
99 static const char *local_machine = "";
100 static const char *remote_arch = "UNKNOWN";
101 #if 0
102 static enum remote_arch_types ra_type = RA_UNKNOWN;
103 #endif
104 static const char *remote_proto = "UNKNOWN";
105 pstring myhostname = "";
106 pstring user_socket_options = "";
108 pstring sesssetup_user = "";
109 static const char *const samlogon_user = "";
111 const BOOL sam_logon_in_ssb = False;
113 pstring global_myname = "";
114 #if 0
115 char **my_netbios_names;
116 #endif /*0 */
119 /****************************************************************************
120 find a suitable temporary directory. The result should be copied immediately
121 as it may be overwritten by a subsequent call
122 ****************************************************************************/
123 const char *
124 tmpdir (void)
126 char *p;
127 if ((p = getenv ("MC_TMPDIR")) || (p = getenv ("TMPDIR")))
129 return p;
131 return "/tmp";
134 /****************************************************************************
135 determine whether we are in the specified group
136 ****************************************************************************/
137 #if 0
138 BOOL
139 in_group (gid_t group, gid_t current_gid, int ngroups, gid_t * groups)
141 int i;
143 if (group == current_gid)
144 return (True);
146 for (i = 0; i < ngroups; i++)
147 if (group == groups[i])
148 return (True);
150 return (False);
154 /****************************************************************************
155 like atoi but gets the value up to the separater character
156 ****************************************************************************/
157 char *
158 Atoic (char *p, int *n, char *c)
160 if (!isdigit ((int) *p))
162 DEBUG (5, ("Atoic: malformed number\n"));
163 return NULL;
166 (*n) = atoi (p);
168 while ((*p) && isdigit ((int) *p))
170 p++;
173 if (strchr (c, *p) == NULL)
175 DEBUG (5, ("Atoic: no separator characters (%s) not found\n", c));
176 return NULL;
179 return p;
182 /*************************************************************************
183 reads a list of numbers
184 *************************************************************************/
185 char *
186 get_numlist (char *p, uint32 ** num, int *count)
188 int val;
190 if (num == NULL || count == NULL)
192 return NULL;
195 (*count) = 0;
196 (*num) = NULL;
198 while ((p = Atoic (p, &val, ":,")) != NULL && (*p) != ':')
200 (*num) = Realloc ((*num), ((*count) + 1) * sizeof (uint32));
201 if ((*num) == NULL)
203 return NULL;
205 (*num)[(*count)] = val;
206 (*count)++;
207 p++;
210 return p;
212 #endif /* 0 */
213 /*******************************************************************
214 copy an IP address from one buffer to another
215 ********************************************************************/
216 void
217 putip (void *dest, void *src)
219 memcpy (dest, src, 4);
223 #define TRUNCATE_NETBIOS_NAME 1
224 #if 0
225 /*******************************************************************
226 convert, possibly using a stupid microsoft-ism which has destroyed
227 the transport independence of netbios (for CIFS vendors that usually
228 use the Win95-type methods, not for NT to NT communication, which uses
229 DCE/RPC and therefore full-length unicode strings...) a dns name into
230 a netbios name.
232 the netbios name (NOT necessarily null-terminated) is truncated to 15
233 characters.
235 ******************************************************************/
236 char *
237 dns_to_netbios_name (char *dns_name)
239 static char netbios_name[16];
240 int i;
241 StrnCpy (netbios_name, dns_name, 15);
242 netbios_name[15] = 0;
244 #ifdef TRUNCATE_NETBIOS_NAME
245 /* ok. this is because of a stupid microsoft-ism. if the called host
246 name contains a '.', microsoft clients expect you to truncate the
247 netbios name up to and including the '.' this even applies, by
248 mistake, to workgroup (domain) names, which is _really_ daft.
250 for (i = 15; i >= 0; i--)
252 if (netbios_name[i] == '.')
254 netbios_name[i] = 0;
255 break;
258 #endif /* TRUNCATE_NETBIOS_NAME */
260 return netbios_name;
264 /****************************************************************************
265 interpret the weird netbios "name". Return the name type
266 ****************************************************************************/
267 static int
268 name_interpret (char *in, char *out)
270 int ret;
271 int len = (*in++) / 2;
273 *out = 0;
275 if (len > 30 || len < 1)
276 return (0);
278 while (len--)
280 if (in[0] < 'A' || in[0] > 'P' || in[1] < 'A' || in[1] > 'P')
282 *out = 0;
283 return (0);
285 *out = ((in[0] - 'A') << 4) + (in[1] - 'A');
286 in += 2;
287 out++;
289 *out = 0;
290 ret = out[-1];
292 #ifdef NETBIOS_SCOPE
293 /* Handle any scope names */
294 while (*in)
296 *out++ = '.'; /* Scope names are separated by periods */
297 len = *(unsigned char *) in++;
298 StrnCpy (out, in, len);
299 out += len;
300 *out = 0;
301 in += len;
303 #endif
304 return (ret);
306 #endif /* 0 */
308 /****************************************************************************
309 mangle a name into netbios format
311 Note: <Out> must be (33 + strlen(scope) + 2) bytes long, at minimum.
312 ****************************************************************************/
314 name_mangle (char *In, char *Out, char name_type)
316 int i;
317 int c;
318 int len;
319 char buf[20];
320 char *p = Out;
321 extern pstring global_scope;
323 /* Safely copy the input string, In, into buf[]. */
324 (void) memset (buf, 0, 20);
325 if (strcmp (In, "*") == 0)
326 buf[0] = '*';
327 else
328 (void) slprintf (buf, sizeof (buf) - 1, "%-15.15s%c", In, name_type);
330 /* Place the length of the first field into the output buffer. */
331 p[0] = 32;
332 p++;
334 /* Now convert the name to the rfc1001/1002 format. */
335 for (i = 0; i < 16; i++)
337 c = toupper (buf[i]);
338 p[i * 2] = ((c >> 4) & 0x000F) + 'A';
339 p[(i * 2) + 1] = (c & 0x000F) + 'A';
341 p += 32;
342 p[0] = '\0';
344 /* Add the scope string. */
345 for (i = 0, len = 0; NULL != global_scope; i++, len++)
347 switch (global_scope[i])
349 case '\0':
350 p[0] = len;
351 if (len > 0)
352 p[len + 1] = 0;
353 return (name_len (Out));
354 case '.':
355 p[0] = len;
356 p += (len + 1);
357 len = -1;
358 break;
359 default:
360 p[len + 1] = global_scope[i];
361 break;
365 return (name_len (Out));
366 } /* name_mangle */
368 /*******************************************************************
369 check if a file exists
370 ********************************************************************/
371 BOOL
372 file_exist (char *fname, SMB_STRUCT_STAT * sbuf)
374 SMB_STRUCT_STAT st;
375 if (!sbuf)
376 sbuf = &st;
378 if (sys_stat (fname, sbuf) != 0)
379 return (False);
381 return (S_ISREG (sbuf->st_mode));
384 /*******************************************************************
385 check a files mod time
386 ********************************************************************/
387 time_t
388 file_modtime (char *fname)
390 SMB_STRUCT_STAT st;
392 if (sys_stat (fname, &st) != 0)
393 return (0);
395 return (st.st_mtime);
398 #if 0
399 /*******************************************************************
400 check if a directory exists
401 ********************************************************************/
402 BOOL
403 directory_exist (char *dname, SMB_STRUCT_STAT * st)
405 SMB_STRUCT_STAT st2;
406 BOOL ret;
408 if (!st)
409 st = &st2;
411 if (sys_stat (dname, st) != 0)
412 return (False);
414 ret = S_ISDIR (st->st_mode);
415 if (!ret)
416 errno = ENOTDIR;
417 return ret;
420 /*******************************************************************
421 returns the size in bytes of the named file
422 ********************************************************************/
423 SMB_OFF_T
424 file_size (char *file_name)
426 SMB_STRUCT_STAT buf;
427 buf.st_size = 0;
428 if (sys_stat (file_name, &buf) != 0)
429 return (SMB_OFF_T) - 1;
430 return (buf.st_size);
432 #endif /* 0 */
434 /*******************************************************************
435 return a string representing an attribute for a file
436 ********************************************************************/
437 char *
438 attrib_string (uint16 mode)
440 static fstring attrstr;
442 attrstr[0] = 0;
444 if (mode & aVOLID)
445 fstrcat (attrstr, "V");
446 if (mode & aDIR)
447 fstrcat (attrstr, "D");
448 if (mode & aARCH)
449 fstrcat (attrstr, "A");
450 if (mode & aHIDDEN)
451 fstrcat (attrstr, "H");
452 if (mode & aSYSTEM)
453 fstrcat (attrstr, "S");
454 if (mode & aRONLY)
455 fstrcat (attrstr, "R");
457 return (attrstr);
460 #if 0
461 /****************************************************************************
462 make a file into unix format
463 ****************************************************************************/
464 void
465 unix_format (char *fname)
467 string_replace (fname, '\\', '/');
470 /****************************************************************************
471 make a file into dos format
472 ****************************************************************************/
473 void
474 dos_format (char *fname)
476 string_replace (fname, '/', '\\');
478 #endif /* 0 */
479 /*******************************************************************
480 show a smb message structure
481 ********************************************************************/
482 void
483 show_msg (char *buf)
485 int i;
486 int bcc = 0;
488 if (DEBUGLEVEL < 5)
489 return;
491 DEBUG (5,
492 ("size=%d\nsmb_com=0x%x\nsmb_rcls=%d\nsmb_reh=%d\nsmb_err=%d\nsmb_flg=%d\nsmb_flg2=%d\n",
493 smb_len (buf), (int) CVAL (buf, smb_com), (int) CVAL (buf, smb_rcls), (int) CVAL (buf,
494 smb_reh),
495 (int) SVAL (buf, smb_err), (int) CVAL (buf, smb_flg), (int) SVAL (buf, smb_flg2)));
496 DEBUG (5,
497 ("smb_tid=%d\nsmb_pid=%d\nsmb_uid=%d\nsmb_mid=%d\nsmt_wct=%d\n",
498 (int) SVAL (buf, smb_tid), (int) SVAL (buf, smb_pid), (int) SVAL (buf, smb_uid),
499 (int) SVAL (buf, smb_mid), (int) CVAL (buf, smb_wct)));
501 for (i = 0; i < (int) CVAL (buf, smb_wct); i++)
503 DEBUG (5, ("smb_vwv[%d]=%d (0x%X)\n", i,
504 SVAL (buf, smb_vwv + 2 * i), SVAL (buf, smb_vwv + 2 * i)));
507 bcc = (int) SVAL (buf, smb_vwv + 2 * (CVAL (buf, smb_wct)));
509 DEBUG (5, ("smb_bcc=%d\n", bcc));
511 if (DEBUGLEVEL < 10)
512 return;
514 if (DEBUGLEVEL < 50)
516 bcc = MIN (bcc, 512);
519 dump_data (10, smb_buf (buf), bcc);
522 /*******************************************************************
523 return the length of an smb packet
524 ********************************************************************/
526 smb_len (char *buf)
528 return (PVAL (buf, 3) | (PVAL (buf, 2) << 8) | ((PVAL (buf, 1) & 1) << 16));
531 /*******************************************************************
532 set the length of an smb packet
533 ********************************************************************/
534 void
535 _smb_setlen (char *buf, int len)
537 buf[0] = 0;
538 buf[1] = (len & 0x10000) >> 16;
539 buf[2] = (len & 0xFF00) >> 8;
540 buf[3] = len & 0xFF;
543 /*******************************************************************
544 set the length and marker of an smb packet
545 ********************************************************************/
546 void
547 smb_setlen (char *buf, int len)
549 _smb_setlen (buf, len);
551 CVAL (buf, 4) = 0xFF;
552 CVAL (buf, 5) = 'S';
553 CVAL (buf, 6) = 'M';
554 CVAL (buf, 7) = 'B';
557 /*******************************************************************
558 setup the word count and byte count for a smb message
559 ********************************************************************/
561 set_message (char *buf, int num_words, int num_bytes, BOOL zero)
563 if (zero)
564 memset (buf + smb_size, '\0', num_words * 2 + num_bytes);
565 CVAL (buf, smb_wct) = num_words;
566 SSVAL (buf, smb_vwv + num_words * SIZEOFWORD, num_bytes);
567 smb_setlen (buf, smb_size + num_words * 2 + num_bytes - 4);
568 return (smb_size + num_words * 2 + num_bytes);
571 /*******************************************************************
572 return the number of smb words
573 ********************************************************************/
574 static int
575 smb_numwords (char *buf)
577 return (CVAL (buf, smb_wct));
580 /*******************************************************************
581 return the size of the smb_buf region of a message
582 ********************************************************************/
584 smb_buflen (char *buf)
586 return (SVAL (buf, smb_vwv0 + smb_numwords (buf) * 2));
589 /*******************************************************************
590 return a pointer to the smb_buf data area
591 ********************************************************************/
592 static int
593 smb_buf_ofs (char *buf)
595 return (smb_size + CVAL (buf, smb_wct) * 2);
598 /*******************************************************************
599 return a pointer to the smb_buf data area
600 ********************************************************************/
601 char *
602 smb_buf (char *buf)
604 return (buf + smb_buf_ofs (buf));
607 /*******************************************************************
608 return the SMB offset into an SMB buffer
609 ********************************************************************/
611 smb_offset (char *p, char *buf)
613 return (PTR_DIFF (p, buf + 4) + chain_size);
616 #if 0
617 /*******************************************************************
618 reduce a file name, removing .. elements.
619 ********************************************************************/
620 void
621 dos_clean_name (char *s)
623 char *p = NULL;
625 DEBUG (3, ("dos_clean_name [%s]\n", s));
627 /* remove any double slashes */
628 string_sub (s, "\\\\", "\\");
630 while ((p = strstr (s, "\\..\\")) != NULL)
632 pstring s1;
634 *p = 0;
635 pstrcpy (s1, p + 3);
637 if ((p = strrchr (s, '\\')) != NULL)
638 *p = 0;
639 else
640 *s = 0;
641 pstrcat (s, s1);
644 trim_string (s, NULL, "\\..");
646 string_sub (s, "\\.\\", "\\");
649 /*******************************************************************
650 reduce a file name, removing .. elements.
651 ********************************************************************/
652 void
653 unix_clean_name (char *s)
655 char *p = NULL;
657 DEBUG (3, ("unix_clean_name [%s]\n", s));
659 /* remove any double slashes */
660 string_sub (s, "//", "/");
662 /* Remove leading ./ characters */
663 if (strncmp (s, "./", 2) == 0)
665 trim_string (s, "./", NULL);
666 if (*s == 0)
667 pstrcpy (s, "./");
670 while ((p = strstr (s, "/../")) != NULL)
672 pstring s1;
674 *p = 0;
675 pstrcpy (s1, p + 3);
677 if ((p = strrchr (s, '/')) != NULL)
678 *p = 0;
679 else
680 *s = 0;
681 pstrcat (s, s1);
684 trim_string (s, NULL, "/..");
687 /*******************************************************************
688 reduce a file name, removing .. elements and checking that
689 it is below dir in the heirachy. This uses dos_GetWd() and so must be run
690 on the system that has the referenced file system.
692 widelinks are allowed if widelinks is true
693 ********************************************************************/
694 BOOL
695 reduce_name (char *s, char *dir, BOOL widelinks)
697 #ifndef REDUCE_PATHS
698 return True;
699 #else
700 pstring dir2;
701 pstring wd;
702 pstring base_name;
703 pstring newname;
704 char *p = NULL;
705 BOOL relative = (*s != '/');
707 *dir2 = *wd = *base_name = *newname = 0;
709 if (widelinks)
711 unix_clean_name (s);
712 /* can't have a leading .. */
713 if (strncmp (s, "..", 2) == 0 && (s[2] == 0 || s[2] == '/'))
715 DEBUG (3, ("Illegal file name? (%s)\n", s));
716 return (False);
719 if (strlen (s) == 0)
720 pstrcpy (s, "./");
722 return (True);
725 DEBUG (3, ("reduce_name [%s] [%s]\n", s, dir));
727 /* remove any double slashes */
728 string_sub (s, "//", "/");
730 pstrcpy (base_name, s);
731 p = strrchr (base_name, '/');
733 if (!p)
734 return (True);
736 if (!dos_GetWd (wd))
738 DEBUG (0, ("couldn't getwd for %s %s\n", s, dir));
739 return (False);
742 if (dos_ChDir (dir) != 0)
744 DEBUG (0, ("couldn't chdir to %s\n", dir));
745 return (False);
748 if (!dos_GetWd (dir2))
750 DEBUG (0, ("couldn't getwd for %s\n", dir));
751 dos_ChDir (wd);
752 return (False);
755 if (p && (p != base_name))
757 *p = 0;
758 if (strcmp (p + 1, ".") == 0)
759 p[1] = 0;
760 if (strcmp (p + 1, "..") == 0)
761 *p = '/';
764 if (dos_ChDir (base_name) != 0)
766 dos_ChDir (wd);
767 DEBUG (3, ("couldn't chdir for %s %s basename=%s\n", s, dir, base_name));
768 return (False);
771 if (!dos_GetWd (newname))
773 dos_ChDir (wd);
774 DEBUG (2, ("couldn't get wd for %s %s\n", s, dir2));
775 return (False);
778 if (p && (p != base_name))
780 pstrcat (newname, "/");
781 pstrcat (newname, p + 1);
785 size_t l = strlen (dir2);
786 if (dir2[l - 1] == '/')
787 l--;
789 if (strncmp (newname, dir2, l) != 0)
791 dos_ChDir (wd);
792 DEBUG (2,
793 ("Bad access attempt? s=%s dir=%s newname=%s l=%d\n", s, dir2, newname,
794 (int) l));
795 return (False);
798 if (relative)
800 if (newname[l] == '/')
801 pstrcpy (s, newname + l + 1);
802 else
803 pstrcpy (s, newname + l);
805 else
806 pstrcpy (s, newname);
809 dos_ChDir (wd);
811 if (strlen (s) == 0)
812 pstrcpy (s, "./");
814 DEBUG (3, ("reduced to %s\n", s));
815 return (True);
816 #endif
820 /****************************************************************************
821 expand some *s
822 ****************************************************************************/
823 static void
824 expand_one (char *Mask, int len)
826 char *p1;
827 while ((p1 = strchr (Mask, '*')) != NULL)
829 int lfill = (len + 1) - strlen (Mask);
830 int l1 = (p1 - Mask);
831 pstring tmp;
832 pstrcpy (tmp, Mask);
833 memset (tmp + l1, '?', lfill);
834 pstrcpy (tmp + l1 + lfill, Mask + l1 + 1);
835 pstrcpy (Mask, tmp);
839 /****************************************************************************
840 parse out a directory name from a path name. Assumes dos style filenames.
841 ****************************************************************************/
842 static void
843 dirname_dos (char *path, char *buf)
845 split_at_last_component (path, buf, '\\', NULL);
849 /****************************************************************************
850 parse out a filename from a path name. Assumes dos style filenames.
851 ****************************************************************************/
852 static char *
853 filename_dos (char *path, char *buf)
855 char *p = strrchr (path, '\\');
857 if (!p)
858 pstrcpy (buf, path);
859 else
860 pstrcpy (buf, p + 1);
862 return (buf);
865 /****************************************************************************
866 expand a wildcard expression, replacing *s with ?s
867 ****************************************************************************/
868 void
869 expand_mask (char *Mask, BOOL doext)
871 pstring mbeg, mext;
872 pstring dirpart;
873 pstring filepart;
874 BOOL hasdot = False;
875 char *p1;
876 BOOL absolute = (*Mask == '\\');
878 *mbeg = *mext = *dirpart = *filepart = 0;
880 /* parse the directory and filename */
881 if (strchr (Mask, '\\'))
882 dirname_dos (Mask, dirpart);
884 filename_dos (Mask, filepart);
886 pstrcpy (mbeg, filepart);
887 if ((p1 = strchr (mbeg, '.')) != NULL)
889 hasdot = True;
890 *p1 = 0;
891 p1++;
892 pstrcpy (mext, p1);
894 else
896 pstrcpy (mext, "");
897 if (strlen (mbeg) > 8)
899 pstrcpy (mext, mbeg + 8);
900 mbeg[8] = 0;
904 if (*mbeg == 0)
905 pstrcpy (mbeg, "????????");
906 if ((*mext == 0) && doext && !hasdot)
907 pstrcpy (mext, "???");
909 if (strequal (mbeg, "*") && *mext == 0)
910 pstrcpy (mext, "*");
912 /* expand *'s */
913 expand_one (mbeg, 8);
914 if (*mext)
915 expand_one (mext, 3);
917 pstrcpy (Mask, dirpart);
918 if (*dirpart || absolute)
919 pstrcat (Mask, "\\");
920 pstrcat (Mask, mbeg);
921 pstrcat (Mask, ".");
922 pstrcat (Mask, mext);
924 DEBUG (6, ("Mask expanded to [%s]\n", Mask));
928 /****************************************************************************
929 make a dir struct
930 ****************************************************************************/
931 void
932 make_dir_struct (char *buf, char *mask, char *fname, SMB_OFF_T size, int mode, time_t date)
934 char *p;
935 pstring mask2;
937 pstrcpy (mask2, mask);
939 if ((mode & aDIR) != 0)
940 size = 0;
942 memset (buf + 1, ' ', 11);
943 if ((p = strchr (mask2, '.')) != NULL)
945 *p = 0;
946 memcpy (buf + 1, mask2, MIN (strlen (mask2), 8));
947 memcpy (buf + 9, p + 1, MIN (strlen (p + 1), 3));
948 *p = '.';
950 else
951 memcpy (buf + 1, mask2, MIN (strlen (mask2), 11));
953 memset (buf + 21, '\0', DIR_STRUCT_SIZE - 21);
954 CVAL (buf, 21) = mode;
955 put_dos_date (buf, 22, date);
956 SSVAL (buf, 26, size & 0xFFFF);
957 SSVAL (buf, 28, (size >> 16) & 0xFFFF);
958 StrnCpy (buf + 30, fname, 12);
959 if (!case_sensitive)
960 strupper (buf + 30);
961 DEBUG (8, ("put name [%s] into dir struct\n", buf + 30));
965 /*******************************************************************
966 close the low 3 fd's and open dev/null in their place
967 ********************************************************************/
968 void
969 close_low_fds (void)
971 int fd;
972 int i;
973 close (0);
974 close (1);
975 close (2);
976 /* try and use up these file descriptors, so silly
977 library routines writing to stdout etc won't cause havoc */
978 for (i = 0; i < 3; i++)
980 fd = sys_open ("/dev/null", O_RDWR, 0);
981 if (fd < 0)
982 fd = sys_open ("/dev/null", O_WRONLY, 0);
983 if (fd < 0)
985 DEBUG (0, ("Cannot open /dev/null\n"));
986 return;
988 if (fd != i)
990 DEBUG (0, ("Didn't get file descriptor %d\n", i));
991 return;
995 #endif /* 0 */
997 /****************************************************************************
998 Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
999 else
1000 if SYSV use O_NDELAY
1001 if BSD use FNDELAY
1002 ****************************************************************************/
1004 set_blocking (int fd, BOOL set)
1006 int val;
1007 #ifdef O_NONBLOCK
1008 #define FLAG_TO_SET O_NONBLOCK
1009 #else
1010 #ifdef SYSV
1011 #define FLAG_TO_SET O_NDELAY
1012 #else /* BSD */
1013 #define FLAG_TO_SET FNDELAY
1014 #endif
1015 #endif
1017 if ((val = fcntl (fd, F_GETFL, 0)) == -1)
1018 return -1;
1019 if (set) /* Turn blocking on - ie. clear nonblock flag */
1020 val &= ~FLAG_TO_SET;
1021 else
1022 val |= FLAG_TO_SET;
1023 return fcntl (fd, F_SETFL, val);
1024 #undef FLAG_TO_SET
1028 /*******************************************************************
1029 find the difference in milliseconds between two struct timeval
1030 values
1031 ********************************************************************/
1033 TvalDiff (struct timeval *tvalold, struct timeval *tvalnew)
1035 return ((tvalnew->tv_sec - tvalold->tv_sec) * 1000 +
1036 ((int) tvalnew->tv_usec - (int) tvalold->tv_usec) / 1000);
1040 #if 0
1041 /****************************************************************************
1042 transfer some data between two fd's
1043 ****************************************************************************/
1044 SMB_OFF_T
1045 transfer_file (int infd, int outfd, SMB_OFF_T n, char *header, int headlen, int align)
1047 static char *buf = NULL;
1048 static int size = 0;
1049 char *buf1, *abuf;
1050 SMB_OFF_T total = 0;
1052 DEBUG (4, ("transfer_file n=%.0f (head=%d) called\n", (double) n, headlen));
1054 if (size == 0)
1056 size = lp_readsize ();
1057 size = MAX (size, 1024);
1060 while (!buf && size > 0)
1062 buf = (char *) Realloc (buf, size + 8);
1063 if (!buf)
1064 size /= 2;
1067 if (!buf)
1069 DEBUG (0, ("Cannot allocate transfer buffer!\n"));
1070 exit (1);
1073 abuf = buf + (align % 8);
1075 if (header)
1076 n += headlen;
1078 while (n > 0)
1080 int s = (int) MIN (n, (SMB_OFF_T) size);
1081 int ret, ret2 = 0;
1083 ret = 0;
1085 if (header && (headlen >= MIN (s, 1024)))
1087 buf1 = header;
1088 s = headlen;
1089 ret = headlen;
1090 headlen = 0;
1091 header = NULL;
1093 else
1095 buf1 = abuf;
1098 if (header && headlen > 0)
1100 ret = MIN (headlen, size);
1101 memcpy (buf1, header, ret);
1102 headlen -= ret;
1103 header += ret;
1104 if (headlen <= 0)
1105 header = NULL;
1108 if (s > ret)
1109 ret += read (infd, buf1 + ret, s - ret);
1111 if (ret > 0)
1113 ret2 = (outfd >= 0 ? write_data (outfd, buf1, ret) : ret);
1114 if (ret2 > 0)
1115 total += ret2;
1116 /* if we can't write then dump excess data */
1117 if (ret2 != ret)
1118 transfer_file (infd, -1, n - (ret + headlen), NULL, 0, 0);
1120 if (ret <= 0 || ret2 != ret)
1121 return (total);
1122 n -= ret;
1124 return (total);
1128 /****************************************************************************
1129 find a pointer to a netbios name
1130 ****************************************************************************/
1131 static char *
1132 name_ptr (char *buf, int ofs)
1134 unsigned char c = *(unsigned char *) (buf + ofs);
1136 if ((c & 0xC0) == 0xC0)
1138 uint16 l;
1139 char p[2];
1140 memcpy (p, buf + ofs, 2);
1141 p[0] &= ~0xC0;
1142 l = RSVAL (p, 0);
1143 DEBUG (5, ("name ptr to pos %d from %d is %s\n", l, ofs, buf + l));
1144 return (buf + l);
1146 else
1147 return (buf + ofs);
1150 /****************************************************************************
1151 extract a netbios name from a buf
1152 ****************************************************************************/
1154 name_extract (char *buf, int ofs, char *name)
1156 char *p = name_ptr (buf, ofs);
1157 int d = PTR_DIFF (p, buf + ofs);
1158 pstrcpy (name, "");
1159 if (d < -50 || d > 50)
1160 return (0);
1161 return (name_interpret (p, name));
1163 #endif /* 0 */
1165 /****************************************************************************
1166 return the total storage length of a mangled name
1167 ****************************************************************************/
1169 name_len (char *s1)
1171 /* NOTE: this argument _must_ be unsigned */
1172 unsigned char *s = (unsigned char *) s1;
1173 int len;
1175 /* If the two high bits of the byte are set, return 2. */
1176 if (0xC0 == (*s & 0xC0))
1177 return (2);
1179 /* Add up the length bytes. */
1180 for (len = 1; (*s); s += (*s) + 1)
1182 len += *s + 1;
1183 SMB_ASSERT (len < 80);
1186 return (len);
1187 } /* name_len */
1190 /*******************************************************************
1191 sleep for a specified number of milliseconds
1192 ********************************************************************/
1193 void
1194 msleep (int t)
1196 int tdiff = 0;
1197 struct timeval tval, t1, t2;
1198 fd_set fds;
1200 GetTimeOfDay (&t1);
1201 GetTimeOfDay (&t2);
1203 while (tdiff < t)
1205 tval.tv_sec = (t - tdiff) / 1000;
1206 tval.tv_usec = 1000 * ((t - tdiff) % 1000);
1208 FD_ZERO (&fds);
1209 errno = 0;
1210 sys_select (0, &fds, &tval);
1212 GetTimeOfDay (&t2);
1213 tdiff = TvalDiff (&t1, &t2);
1217 #if 0
1218 /*********************************************************
1219 * Recursive routine that is called by unix_mask_match.
1220 * Does the actual matching. This is the 'original code'
1221 * used by the unix matcher.
1222 *********************************************************/
1223 static BOOL
1224 unix_do_match (char *str, char *regexp, int case_sig)
1226 char *p;
1228 for (p = regexp; *p && *str;)
1230 switch (*p)
1232 case '?':
1233 str++;
1234 p++;
1235 break;
1237 case '*':
1238 /* Look for a character matching
1239 the one after the '*' */
1240 p++;
1241 if (!*p)
1242 return True; /* Automatic match */
1243 while (*str)
1245 while (*str && (case_sig ? (*p != *str) : (toupper (*p) != toupper (*str))))
1246 str++;
1247 if (unix_do_match (str, p, case_sig))
1248 return True;
1249 if (!*str)
1250 return False;
1251 else
1252 str++;
1254 return False;
1256 default:
1257 if (case_sig)
1259 if (*str != *p)
1260 return False;
1262 else
1264 if (toupper (*str) != toupper (*p))
1265 return False;
1267 str++, p++;
1268 break;
1271 if (!*p && !*str)
1272 return True;
1274 if (!*p && str[0] == '.' && str[1] == 0)
1275 return (True);
1277 if (!*str && *p == '?')
1279 while (*p == '?')
1280 p++;
1281 return (!*p);
1284 if (!*str && (*p == '*' && p[1] == '\0'))
1285 return True;
1286 return False;
1290 /*********************************************************
1291 * Routine to match a given string with a regexp - uses
1292 * simplified regexp that takes * and ? only. Case can be
1293 * significant or not.
1294 * This is the 'original code' used by the unix matcher.
1295 *********************************************************/
1297 static BOOL
1298 unix_mask_match (char *str, char *regexp, int case_sig, BOOL trans2)
1300 char *p;
1301 pstring p1, p2;
1302 fstring ebase, eext, sbase, sext;
1304 BOOL matched;
1306 /* Make local copies of str and regexp */
1307 StrnCpy (p1, regexp, sizeof (pstring) - 1);
1308 StrnCpy (p2, str, sizeof (pstring) - 1);
1310 if (!strchr (p2, '.'))
1312 pstrcat (p2, ".");
1315 /* Remove any *? and ** as they are meaningless */
1316 for (p = p1; *p; p++)
1317 while (*p == '*' && (p[1] == '?' || p[1] == '*'))
1318 (void) pstrcpy (&p[1], &p[2]);
1320 if (strequal (p1, "*"))
1321 return (True);
1323 DEBUG (8, ("unix_mask_match str=<%s> regexp=<%s>, case_sig = %d\n", p2, p1, case_sig));
1325 if (trans2)
1327 fstrcpy (ebase, p1);
1328 fstrcpy (sbase, p2);
1330 else
1332 if ((p = strrchr (p1, '.')))
1334 *p = 0;
1335 fstrcpy (ebase, p1);
1336 fstrcpy (eext, p + 1);
1338 else
1340 fstrcpy (ebase, p1);
1341 eext[0] = 0;
1344 if (!strequal (p2, ".") && !strequal (p2, "..") && (p = strrchr (p2, '.')))
1346 *p = 0;
1347 fstrcpy (sbase, p2);
1348 fstrcpy (sext, p + 1);
1350 else
1352 fstrcpy (sbase, p2);
1353 fstrcpy (sext, "");
1357 matched = unix_do_match (sbase, ebase, case_sig) &&
1358 (trans2 || unix_do_match (sext, eext, case_sig));
1360 DEBUG (8, ("unix_mask_match returning %d\n", matched));
1362 return matched;
1365 /*********************************************************
1366 * Recursive routine that is called by mask_match.
1367 * Does the actual matching. Returns True if matched,
1368 * False if failed. This is the 'new' NT style matcher.
1369 *********************************************************/
1371 BOOL
1372 do_match (char *str, char *regexp, int case_sig)
1374 char *p;
1376 for (p = regexp; *p && *str;)
1378 switch (*p)
1380 case '?':
1381 str++;
1382 p++;
1383 break;
1385 case '*':
1386 /* Look for a character matching
1387 the one after the '*' */
1388 p++;
1389 if (!*p)
1390 return True; /* Automatic match */
1391 while (*str)
1393 while (*str && (case_sig ? (*p != *str) : (toupper (*p) != toupper (*str))))
1394 str++;
1395 /* Now eat all characters that match, as
1396 we want the *last* character to match. */
1397 while (*str && (case_sig ? (*p == *str) : (toupper (*p) == toupper (*str))))
1398 str++;
1399 str--; /* We've eaten the match char after the '*' */
1400 if (do_match (str, p, case_sig))
1402 return True;
1404 if (!*str)
1406 return False;
1408 else
1410 str++;
1413 return False;
1415 default:
1416 if (case_sig)
1418 if (*str != *p)
1420 return False;
1423 else
1425 if (toupper (*str) != toupper (*p))
1427 return False;
1430 str++, p++;
1431 break;
1435 if (!*p && !*str)
1436 return True;
1438 if (!*p && str[0] == '.' && str[1] == 0)
1440 return (True);
1443 if (!*str && *p == '?')
1445 while (*p == '?')
1446 p++;
1447 return (!*p);
1450 if (!*str && (*p == '*' && p[1] == '\0'))
1452 return True;
1455 return False;
1459 /*********************************************************
1460 * Routine to match a given string with a regexp - uses
1461 * simplified regexp that takes * and ? only. Case can be
1462 * significant or not.
1463 * The 8.3 handling was rewritten by Ums Harald <Harald.Ums@pro-sieben.de>
1464 * This is the new 'NT style' matcher.
1465 *********************************************************/
1467 BOOL
1468 mask_match (char *str, char *regexp, int case_sig, BOOL trans2)
1470 char *p;
1471 pstring t_pattern, t_filename, te_pattern, te_filename;
1472 fstring ebase, eext, sbase, sext;
1474 BOOL matched = False;
1476 /* Make local copies of str and regexp */
1477 pstrcpy (t_pattern, regexp);
1478 pstrcpy (t_filename, str);
1480 if (trans2)
1483 /* a special case for 16 bit apps */
1484 if (strequal (t_pattern, "????????.???"))
1485 pstrcpy (t_pattern, "*");
1487 #if 0
1489 * Handle broken clients that send us old 8.3 format.
1491 string_sub (t_pattern, "????????", "*");
1492 string_sub (t_pattern, ".???", ".*");
1493 #endif
1496 #if 0
1498 * Not sure if this is a good idea. JRA.
1500 if (trans2 && is_8_3 (t_pattern, False) && is_8_3 (t_filename, False))
1501 trans2 = False;
1502 #endif
1504 #if 0
1505 if (!strchr (t_filename, '.'))
1507 pstrcat (t_filename, ".");
1509 #endif
1511 /* Remove any *? and ** as they are meaningless */
1512 string_sub (t_pattern, "*?", "*");
1513 string_sub (t_pattern, "**", "*");
1515 if (strequal (t_pattern, "*"))
1516 return (True);
1518 DEBUG (8,
1519 ("mask_match str=<%s> regexp=<%s>, case_sig = %d\n", t_filename, t_pattern, case_sig));
1521 if (trans2)
1524 * Match each component of the regexp, split up by '.'
1525 * characters.
1527 char *fp, *rp, *cp2, *cp1;
1528 BOOL last_wcard_was_star = False;
1529 int num_path_components, num_regexp_components;
1531 pstrcpy (te_pattern, t_pattern);
1532 pstrcpy (te_filename, t_filename);
1534 * Remove multiple "*." patterns.
1536 string_sub (te_pattern, "*.*.", "*.");
1537 num_regexp_components = count_chars (te_pattern, '.');
1538 num_path_components = count_chars (te_filename, '.');
1541 * Check for special 'hack' case of "DIR a*z". - needs to match a.b.c...z
1543 if (num_regexp_components == 0)
1544 matched = do_match (te_filename, te_pattern, case_sig);
1545 else
1547 for (cp1 = te_pattern, cp2 = te_filename; cp1;)
1549 fp = strchr (cp2, '.');
1550 if (fp)
1551 *fp = '\0';
1552 rp = strchr (cp1, '.');
1553 if (rp)
1554 *rp = '\0';
1556 if (cp1[strlen (cp1) - 1] == '*')
1557 last_wcard_was_star = True;
1558 else
1559 last_wcard_was_star = False;
1561 if (!do_match (cp2, cp1, case_sig))
1562 break;
1564 cp1 = rp ? rp + 1 : NULL;
1565 cp2 = fp ? fp + 1 : "";
1567 if (last_wcard_was_star || ((cp1 != NULL) && (*cp1 == '*')))
1569 /* Eat the extra path components. */
1570 int i;
1572 for (i = 0; i < num_path_components - num_regexp_components; i++)
1574 fp = strchr (cp2, '.');
1575 if (fp)
1576 *fp = '\0';
1578 if ((cp1 != NULL) && do_match (cp2, cp1, case_sig))
1580 cp2 = fp ? fp + 1 : "";
1581 break;
1583 cp2 = fp ? fp + 1 : "";
1585 num_path_components -= i;
1588 if (cp1 == NULL && ((*cp2 == '\0') || last_wcard_was_star))
1589 matched = True;
1592 else
1595 /* -------------------------------------------------
1596 * Behaviour of Win95
1597 * for 8.3 filenames and 8.3 Wildcards
1598 * -------------------------------------------------
1600 if (strequal (t_filename, "."))
1603 * Patterns: *.* *. ?. ? ????????.??? are valid.
1606 if (strequal (t_pattern, "*.*") || strequal (t_pattern, "*.") ||
1607 strequal (t_pattern, "????????.???") ||
1608 strequal (t_pattern, "?.") || strequal (t_pattern, "?"))
1609 matched = True;
1611 else if (strequal (t_filename, ".."))
1614 * Patterns: *.* *. ?. ? *.? ????????.??? are valid.
1617 if (strequal (t_pattern, "*.*") || strequal (t_pattern, "*.") ||
1618 strequal (t_pattern, "?.") || strequal (t_pattern, "?") ||
1619 strequal (t_pattern, "????????.???") ||
1620 strequal (t_pattern, "*.?") || strequal (t_pattern, "?.*"))
1621 matched = True;
1623 else
1626 if ((p = strrchr (t_pattern, '.')))
1629 * Wildcard has a suffix.
1631 *p = 0;
1632 fstrcpy (ebase, t_pattern);
1633 if (p[1])
1635 fstrcpy (eext, p + 1);
1637 else
1639 /* pattern ends in DOT: treat as if there is no DOT */
1640 *eext = 0;
1641 if (strequal (ebase, "*"))
1642 return (True);
1645 else
1648 * No suffix for wildcard.
1650 fstrcpy (ebase, t_pattern);
1651 eext[0] = 0;
1654 p = strrchr (t_filename, '.');
1655 if (p && (p[1] == 0))
1658 * Filename has an extension of '.' only.
1660 *p = 0; /* nuke dot at end of string */
1661 p = 0; /* and treat it as if there is no extension */
1664 if (p)
1667 * Filename has an extension.
1669 *p = 0;
1670 fstrcpy (sbase, t_filename);
1671 fstrcpy (sext, p + 1);
1672 if (*eext)
1674 matched = do_match (sbase, ebase, case_sig) && do_match (sext, eext, case_sig);
1676 else
1678 /* pattern has no extension */
1679 /* Really: match complete filename with pattern ??? means exactly 3 chars */
1680 matched = do_match (str, ebase, case_sig);
1683 else
1686 * Filename has no extension.
1688 fstrcpy (sbase, t_filename);
1689 fstrcpy (sext, "");
1690 if (*eext)
1692 /* pattern has extension */
1693 matched = do_match (sbase, ebase, case_sig) && do_match (sext, eext, case_sig);
1695 else
1697 matched = do_match (sbase, ebase, case_sig);
1698 #ifdef EMULATE_WEIRD_W95_MATCHING
1700 * Even Microsoft has some problems
1701 * Behaviour Win95 -> local disk
1702 * is different from Win95 -> smb drive from Nt 4.0
1703 * This branch would reflect the Win95 local disk behaviour
1705 if (!matched)
1707 /* a? matches aa and a in w95 */
1708 fstrcat (sbase, ".");
1709 matched = do_match (sbase, ebase, case_sig);
1711 #endif
1717 DEBUG (8, ("mask_match returning %d\n", matched));
1719 return matched;
1721 #endif /* 0 */
1723 #if 0
1724 /****************************************************************************
1725 set the length of a file from a filedescriptor.
1726 Returns 0 on success, -1 on failure.
1727 ****************************************************************************/
1730 set_filelen (int fd, SMB_OFF_T len)
1732 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1733 extend a file with ftruncate. Provide alternate implementation
1734 for this */
1736 #ifdef HAVE_FTRUNCATE_EXTEND
1737 return sys_ftruncate (fd, len);
1738 #else
1739 SMB_STRUCT_STAT st;
1740 char c = 0;
1741 SMB_OFF_T currpos = sys_lseek (fd, (SMB_OFF_T) 0, SEEK_CUR);
1743 if (currpos == -1)
1744 return -1;
1745 /* Do an fstat to see if the file is longer than
1746 the requested size (call ftruncate),
1747 or shorter, in which case seek to len - 1 and write 1
1748 byte of zero */
1749 if (sys_fstat (fd, &st) < 0)
1750 return -1;
1752 #ifdef S_ISFIFO
1753 if (S_ISFIFO (st.st_mode))
1754 return 0;
1755 #endif
1757 if (st.st_size == len)
1758 return 0;
1759 if (st.st_size > len)
1760 return sys_ftruncate (fd, len);
1762 if (sys_lseek (fd, len - 1, SEEK_SET) != len - 1)
1763 return -1;
1764 if (write (fd, &c, 1) != 1)
1765 return -1;
1766 /* Seek to where we were */
1767 if (sys_lseek (fd, currpos, SEEK_SET) != currpos)
1768 return -1;
1769 return 0;
1770 #endif
1774 #ifdef HPUX
1775 /****************************************************************************
1776 this is a version of setbuffer() for those machines that only have setvbuf
1777 ****************************************************************************/
1778 void
1779 setbuffer (FILE * f, char *buf, int bufsize)
1781 setvbuf (f, buf, _IOFBF, bufsize);
1783 #endif
1784 #endif /* 0 */
1788 /****************************************************************************
1789 expand a pointer to be a particular size
1790 ****************************************************************************/
1791 void *
1792 Realloc (void *p, size_t size)
1794 void *ret = NULL;
1796 if (size == 0)
1798 if (p)
1799 free (p);
1800 DEBUG (5, ("Realloc asked for 0 bytes\n"));
1801 return NULL;
1804 if (!p)
1805 ret = (void *) malloc (size);
1806 else
1807 ret = (void *) realloc (p, size);
1809 #ifdef MEM_MAN
1811 extern FILE *dbf;
1812 smb_mem_write_info (ret, dbf);
1814 #endif
1816 if (!ret)
1817 DEBUG (0, ("Memory allocation error: failed to expand to %d bytes\n", (int) size));
1819 return (ret);
1823 /****************************************************************************
1824 get my own name and IP
1825 ****************************************************************************/
1826 BOOL
1827 get_myname (char *my_name, struct in_addr * ip)
1829 struct hostent *hp;
1830 pstring hostname;
1832 *hostname = 0;
1834 /* get my host name */
1835 if (gethostname (hostname, sizeof (hostname)) == -1)
1837 DEBUG (0, ("gethostname failed\n"));
1838 return False;
1841 /* Ensure null termination. */
1842 hostname[sizeof (hostname) - 1] = '\0';
1844 /* get host info */
1845 if ((hp = Get_Hostbyname (hostname)) == 0)
1847 DEBUG (0, ("Get_Hostbyname: Unknown host %s\n", hostname));
1848 return False;
1851 if (my_name)
1853 /* split off any parts after an initial . */
1854 char *p = strchr (hostname, '.');
1855 if (p)
1856 *p = 0;
1858 fstrcpy (my_name, hostname);
1861 if (ip)
1862 putip ((char *) ip, (char *) hp->h_addr);
1864 return (True);
1868 /****************************************************************************
1869 true if two IP addresses are equal
1870 ****************************************************************************/
1871 BOOL
1872 ip_equal (struct in_addr ip1, struct in_addr ip2)
1874 uint32 a1, a2;
1875 a1 = ntohl (ip1.s_addr);
1876 a2 = ntohl (ip2.s_addr);
1877 return (a1 == a2);
1880 #if 0 /* May be useful one day */
1881 /****************************************************************************
1882 interpret a protocol description string, with a default
1883 ****************************************************************************/
1885 interpret_protocol (char *str, int def)
1887 if (strequal (str, "NT1"))
1888 return (PROTOCOL_NT1);
1889 if (strequal (str, "LANMAN2"))
1890 return (PROTOCOL_LANMAN2);
1891 if (strequal (str, "LANMAN1"))
1892 return (PROTOCOL_LANMAN1);
1893 if (strequal (str, "CORE"))
1894 return (PROTOCOL_CORE);
1895 if (strequal (str, "COREPLUS"))
1896 return (PROTOCOL_COREPLUS);
1897 if (strequal (str, "CORE+"))
1898 return (PROTOCOL_COREPLUS);
1900 DEBUG (0, ("Unrecognised protocol level %s\n", str));
1902 return (def);
1904 #endif /* 0 */
1906 /****************************************************************************
1907 interpret an internet address or name into an IP address in 4 byte form
1908 ****************************************************************************/
1909 uint32
1910 interpret_addr (const char *str)
1912 struct hostent *hp;
1913 uint32 res;
1914 int i;
1915 BOOL pure_address = True;
1917 if (strcmp (str, "0.0.0.0") == 0)
1918 return (0);
1919 if (strcmp (str, "255.255.255.255") == 0)
1920 return (0xFFFFFFFF);
1922 for (i = 0; pure_address && str[i]; i++)
1923 if (!(isdigit ((int) str[i]) || str[i] == '.'))
1924 pure_address = False;
1926 /* if it's in the form of an IP address then get the lib to interpret it */
1927 if (pure_address)
1929 res = inet_addr (str);
1931 else
1933 /* otherwise assume it's a network name of some sort and use
1934 Get_Hostbyname */
1935 if ((hp = Get_Hostbyname (str)) == 0)
1937 DEBUG (3, ("Get_Hostbyname: Unknown host. %s\n", str));
1938 return 0;
1940 if (hp->h_addr == NULL)
1942 DEBUG (3, ("Get_Hostbyname: host address is invalid for host %s\n", str));
1943 return 0;
1945 putip ((char *) &res, (char *) hp->h_addr);
1948 if (res == (uint32) - 1)
1949 return (0);
1951 return (res);
1954 /*******************************************************************
1955 a convenient addition to interpret_addr()
1956 ******************************************************************/
1957 struct in_addr *
1958 interpret_addr2 (const char *str)
1960 static struct in_addr ret;
1961 uint32 a = interpret_addr (str);
1962 ret.s_addr = a;
1963 return (&ret);
1966 /*******************************************************************
1967 check if an IP is the 0.0.0.0
1968 ******************************************************************/
1969 BOOL
1970 zero_ip (struct in_addr ip)
1972 uint32 a;
1973 putip ((char *) &a, (char *) &ip);
1974 return (a == 0);
1978 /*******************************************************************
1979 matchname - determine if host name matches IP address
1980 ******************************************************************/
1981 BOOL
1982 matchname (char *remotehost, struct in_addr addr)
1984 struct hostent *hp;
1985 int i;
1987 if ((hp = Get_Hostbyname (remotehost)) == 0)
1989 DEBUG (0, ("Get_Hostbyname(%s): lookup failure.\n", remotehost));
1990 return False;
1994 * Make sure that gethostbyname() returns the "correct" host name.
1995 * Unfortunately, gethostbyname("localhost") sometimes yields
1996 * "localhost.domain". Since the latter host name comes from the
1997 * local DNS, we just have to trust it (all bets are off if the local
1998 * DNS is perverted). We always check the address list, though.
2001 if (strcasecmp (remotehost, hp->h_name) && strcasecmp (remotehost, "localhost"))
2003 DEBUG (0, ("host name/name mismatch: %s != %s\n", remotehost, hp->h_name));
2004 return False;
2007 /* Look up the host address in the address list we just got. */
2008 for (i = 0; hp->h_addr_list[i]; i++)
2010 if (memcmp (hp->h_addr_list[i], (caddr_t) & addr, sizeof (addr)) == 0)
2011 return True;
2015 * The host name does not map to the original host address. Perhaps
2016 * someone has compromised a name server. More likely someone botched
2017 * it, but that could be dangerous, too.
2020 DEBUG (0, ("host name/address mismatch: %s != %s\n", inet_ntoa (addr), hp->h_name));
2021 return False;
2025 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
2026 /******************************************************************
2027 Remove any mount options such as -rsize=2048,wsize=2048 etc.
2028 Based on a fix from <Thomas.Hepper@icem.de>.
2029 *******************************************************************/
2031 static void
2032 strip_mount_options (pstring * str)
2034 if (**str == '-')
2036 char *p = *str;
2037 while (*p && !isspace (*p))
2038 p++;
2039 while (*p && isspace (*p))
2040 p++;
2041 if (*p)
2043 pstring tmp_str;
2045 pstrcpy (tmp_str, p);
2046 pstrcpy (*str, tmp_str);
2051 /*******************************************************************
2052 Patch from jkf@soton.ac.uk
2053 Split Luke's automount_server into YP lookup and string splitter
2054 so can easily implement automount_path().
2055 As we may end up doing both, cache the last YP result.
2056 *******************************************************************/
2058 #ifdef WITH_NISPLUS_HOME
2059 static char *
2060 automount_lookup (char *user_name)
2062 static fstring last_key = "";
2063 static pstring last_value = "";
2065 char *nis_map = (char *) lp_nis_home_map_name ();
2067 char buffer[NIS_MAXATTRVAL + 1];
2068 nis_result *result;
2069 nis_object *object;
2070 entry_obj *entry;
2072 DEBUG (5, ("NIS+ Domain: %s\n", (char *) nis_local_directory ()));
2074 if (strcmp (user_name, last_key))
2076 slprintf (buffer, sizeof (buffer) - 1, "[%s=%s]%s.%s", "key", user_name, nis_map,
2077 (char *) nis_local_directory ());
2078 DEBUG (5, ("NIS+ querystring: %s\n", buffer));
2080 if (result = nis_list (buffer, RETURN_RESULT, NULL, NULL))
2082 if (result->status != NIS_SUCCESS)
2084 DEBUG (3, ("NIS+ query failed: %s\n", nis_sperrno (result->status)));
2085 fstrcpy (last_key, "");
2086 pstrcpy (last_value, "");
2088 else
2090 object = result->objects.objects_val;
2091 if (object->zo_data.zo_type == ENTRY_OBJ)
2093 entry = &object->zo_data.objdata_u.en_data;
2094 DEBUG (5, ("NIS+ entry type: %s\n", entry->en_type));
2095 DEBUG (3,
2096 ("NIS+ result: %s\n",
2097 entry->en_cols.en_cols_val[1].ec_value.ec_value_val));
2099 pstrcpy (last_value, entry->en_cols.en_cols_val[1].ec_value.ec_value_val);
2100 string_sub (last_value, "&", user_name);
2101 fstrcpy (last_key, user_name);
2105 nis_freeresult (result);
2108 strip_mount_options (&last_value);
2110 DEBUG (4, ("NIS+ Lookup: %s resulted in %s\n", user_name, last_value));
2111 return last_value;
2113 #else /* WITH_NISPLUS_HOME */
2114 static char *
2115 automount_lookup (char *user_name)
2117 static fstring last_key = "";
2118 static pstring last_value = "";
2120 int nis_error; /* returned by yp all functions */
2121 char *nis_result; /* yp_match inits this */
2122 int nis_result_len; /* and set this */
2123 char *nis_domain; /* yp_get_default_domain inits this */
2124 char *nis_map = (char *) lp_nis_home_map_name ();
2126 if ((nis_error = yp_get_default_domain (&nis_domain)) != 0)
2128 DEBUG (3, ("YP Error: %s\n", yperr_string (nis_error)));
2129 return last_value;
2132 DEBUG (5, ("NIS Domain: %s\n", nis_domain));
2134 if (!strcmp (user_name, last_key))
2136 nis_result = last_value;
2137 nis_result_len = strlen (last_value);
2138 nis_error = 0;
2140 else
2142 if ((nis_error = yp_match (nis_domain, nis_map,
2143 user_name, strlen (user_name),
2144 &nis_result, &nis_result_len)) != 0)
2146 DEBUG (3, ("YP Error: \"%s\" while looking up \"%s\" in map \"%s\"\n",
2147 yperr_string (nis_error), user_name, nis_map));
2149 if (!nis_error && nis_result_len >= sizeof (pstring))
2151 nis_result_len = sizeof (pstring) - 1;
2153 fstrcpy (last_key, user_name);
2154 strncpy (last_value, nis_result, nis_result_len);
2155 last_value[nis_result_len] = '\0';
2158 strip_mount_options (&last_value);
2160 DEBUG (4, ("YP Lookup: %s resulted in %s\n", user_name, last_value));
2161 return last_value;
2163 #endif /* WITH_NISPLUS_HOME */
2164 #endif
2166 /*******************************************************************
2167 Patch from jkf@soton.ac.uk
2168 This is Luke's original function with the NIS lookup code
2169 moved out to a separate function.
2170 *******************************************************************/
2171 static char *
2172 automount_server (const char *user_name)
2174 static pstring server_name;
2175 (void) user_name;
2177 /* use the local machine name as the default */
2178 /* this will be the default if WITH_AUTOMOUNT is not used or fails */
2179 pstrcpy (server_name, local_machine);
2181 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
2183 if (lp_nis_home_map ())
2185 int home_server_len;
2186 char *automount_value = automount_lookup (user_name);
2187 home_server_len = strcspn (automount_value, ":");
2188 DEBUG (5, ("NIS lookup succeeded. Home server length: %d\n", home_server_len));
2189 if (home_server_len > sizeof (pstring))
2191 home_server_len = sizeof (pstring);
2193 strncpy (server_name, automount_value, home_server_len);
2194 server_name[home_server_len] = '\0';
2196 #endif
2198 DEBUG (4, ("Home server: %s\n", server_name));
2200 return server_name;
2203 /*******************************************************************
2204 Patch from jkf@soton.ac.uk
2205 Added this to implement %p (NIS auto-map version of %H)
2206 *******************************************************************/
2207 static char *
2208 automount_path (char *user_name)
2210 static pstring server_path;
2212 /* use the passwd entry as the default */
2213 /* this will be the default if WITH_AUTOMOUNT is not used or fails */
2214 /* pstrcpy() copes with get_home_dir() returning NULL */
2215 pstrcpy (server_path, get_home_dir (user_name));
2217 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
2219 if (lp_nis_home_map ())
2221 char *home_path_start;
2222 char *automount_value = automount_lookup (user_name);
2223 home_path_start = strchr (automount_value, ':');
2224 if (home_path_start != NULL)
2226 DEBUG (5, ("NIS lookup succeeded. Home path is: %s\n",
2227 home_path_start ? (home_path_start + 1) : ""));
2228 pstrcpy (server_path, home_path_start + 1);
2231 #endif
2233 DEBUG (4, ("Home server path: %s\n", server_path));
2235 return server_path;
2239 /*******************************************************************
2240 sub strings with useful parameters
2241 Rewritten by Stefaan A Eeckels <Stefaan.Eeckels@ecc.lu> and
2242 Paul Rippin <pr3245@nopc.eurostat.cec.be>
2243 ********************************************************************/
2244 void
2245 standard_sub_basic (char *str)
2247 char *s, *p;
2248 char pidstr[10];
2249 struct passwd *pass;
2250 const char *username = sam_logon_in_ssb ? samlogon_user : sesssetup_user;
2252 for (s = str; s && *s && (p = strchr (s, '%')); s = p)
2254 switch (*(p + 1))
2256 case 'G':
2258 if ((pass = Get_Pwnam (username)) != NULL)
2260 string_sub (p, "%G", gidtoname (pass->pw_gid));
2262 else
2264 p += 2;
2266 break;
2268 case 'N':
2269 string_sub (p, "%N", automount_server (username));
2270 break;
2271 case 'I':
2272 string_sub (p, "%I", client_addr (Client));
2273 break;
2274 case 'L':
2275 string_sub (p, "%L", local_machine);
2276 break;
2277 case 'M':
2278 string_sub (p, "%M", client_name (Client));
2279 break;
2280 case 'R':
2281 string_sub (p, "%R", remote_proto);
2282 break;
2283 case 'T':
2284 string_sub (p, "%T", timestring ());
2285 break;
2286 case 'U':
2287 string_sub (p, "%U", username);
2288 break;
2289 case 'a':
2290 string_sub (p, "%a", remote_arch);
2291 break;
2292 case 'd':
2294 slprintf (pidstr, sizeof (pidstr) - 1, "%d", (int) getpid ());
2295 string_sub (p, "%d", pidstr);
2296 break;
2298 case 'h':
2299 string_sub (p, "%h", myhostname);
2300 break;
2301 case 'm':
2302 string_sub (p, "%m", remote_machine);
2303 break;
2304 case 'v':
2305 string_sub (p, "%v", VERSION);
2306 break;
2307 case '$': /* Expand environment variables */
2309 /* Contributed by Branko Cibej <branko.cibej@hermes.si> */
2310 fstring envname;
2311 char *envval;
2312 char *q, *r;
2313 int copylen;
2315 if (*(p + 2) != '(')
2317 p += 2;
2318 break;
2320 if ((q = strchr (p, ')')) == NULL)
2322 DEBUG (0, ("standard_sub_basic: Unterminated environment \
2323 variable [%s]\n", p));
2324 p += 2;
2325 break;
2328 r = p + 3;
2329 copylen = MIN ((size_t) (q - r), (size_t) (sizeof (envname) - 1));
2330 strncpy (envname, r, copylen);
2331 envname[copylen] = '\0';
2333 if ((envval = getenv (envname)) == NULL)
2335 DEBUG (0, ("standard_sub_basic: Environment variable [%s] not set\n", envname));
2336 p += 2;
2337 break;
2340 copylen = MIN ((size_t) (q + 1 - p), (size_t) (sizeof (envname) - 1));
2341 strncpy (envname, p, copylen);
2342 envname[copylen] = '\0';
2343 string_sub (p, envname, envval);
2344 break;
2346 case '\0':
2347 p++;
2348 break; /* don't run off end if last character is % */
2349 default:
2350 p += 2;
2351 break;
2354 return;
2358 /****************************************************************************
2359 do some standard substitutions in a string
2360 ****************************************************************************/
2361 void
2362 standard_sub (connection_struct * conn, char *str)
2364 char *p, *s;
2365 const char *home;
2367 for (s = str; (p = strchr (s, '%')); s = p)
2369 switch (*(p + 1))
2371 case 'H':
2372 if ((home = get_home_dir (conn->user)))
2374 string_sub (p, "%H", home);
2376 else
2378 p += 2;
2380 break;
2382 case 'P':
2383 string_sub (p, "%P", conn->connectpath);
2384 break;
2386 case 'S':
2387 string_sub (p, "%S", lp_servicename (SNUM (conn)));
2388 break;
2390 case 'g':
2391 string_sub (p, "%g", gidtoname (conn->gid));
2392 break;
2393 case 'u':
2394 string_sub (p, "%u", conn->user);
2395 break;
2397 /* Patch from jkf@soton.ac.uk Left the %N (NIS
2398 * server name) in standard_sub_basic as it is
2399 * a feature for logon servers, hence uses the
2400 * username. The %p (NIS server path) code is
2401 * here as it is used instead of the default
2402 * "path =" string in [homes] and so needs the
2403 * service name, not the username. */
2404 case 'p':
2405 string_sub (p, "%p", automount_path (lp_servicename (SNUM (conn))));
2406 break;
2407 case '\0':
2408 p++;
2409 break; /* don't run off the end of the string
2412 default:
2413 p += 2;
2414 break;
2418 standard_sub_basic (str);
2423 /*******************************************************************
2424 are two IPs on the same subnet?
2425 ********************************************************************/
2426 BOOL
2427 same_net (struct in_addr ip1, struct in_addr ip2, struct in_addr mask)
2429 uint32 net1, net2, nmask;
2431 nmask = ntohl (mask.s_addr);
2432 net1 = ntohl (ip1.s_addr);
2433 net2 = ntohl (ip2.s_addr);
2435 return ((net1 & nmask) == (net2 & nmask));
2439 /****************************************************************************
2440 a wrapper for gethostbyname() that tries with all lower and all upper case
2441 if the initial name fails
2442 ****************************************************************************/
2443 struct hostent *
2444 Get_Hostbyname (const char *name)
2446 char *name2 = strdup (name);
2447 struct hostent *ret;
2449 if (!name2)
2451 DEBUG (0, ("Memory allocation error in Get_Hostbyname! panic\n"));
2452 exit (0);
2457 * This next test is redundent and causes some systems (with
2458 * broken isalnum() calls) problems.
2459 * JRA.
2462 #if 0
2463 if (!isalnum (*name2))
2465 free (name2);
2466 return (NULL);
2468 #endif /* 0 */
2470 ret = sys_gethostbyname (name2);
2471 if (ret != NULL)
2473 free (name2);
2474 return (ret);
2477 /* try with all lowercase */
2478 strlower (name2);
2479 ret = sys_gethostbyname (name2);
2480 if (ret != NULL)
2482 free (name2);
2483 return (ret);
2486 /* try with all uppercase */
2487 strupper (name2);
2488 ret = sys_gethostbyname (name2);
2489 if (ret != NULL)
2491 free (name2);
2492 return (ret);
2495 /* nothing works :-( */
2496 free (name2);
2497 return (NULL);
2501 /*******************************************************************
2502 turn a uid into a user name
2503 ********************************************************************/
2504 char *
2505 uidtoname (uid_t uid)
2507 static char name[40];
2508 struct passwd *pass = getpwuid (uid);
2509 if (pass)
2510 return (pass->pw_name);
2511 slprintf (name, sizeof (name) - 1, "%d", (int) uid);
2512 return (name);
2516 /*******************************************************************
2517 turn a gid into a group name
2518 ********************************************************************/
2520 char *
2521 gidtoname (gid_t gid)
2523 static char name[40];
2524 struct group *grp = getgrgid (gid);
2525 if (grp)
2526 return (grp->gr_name);
2527 slprintf (name, sizeof (name) - 1, "%d", (int) gid);
2528 return (name);
2531 /*******************************************************************
2532 turn a user name into a uid
2533 ********************************************************************/
2534 uid_t
2535 nametouid (const char *name)
2537 struct passwd *pass = getpwnam (name);
2538 if (pass)
2539 return (pass->pw_uid);
2540 return (uid_t) - 1;
2543 /*******************************************************************
2544 something really nasty happened - panic!
2545 ********************************************************************/
2546 void
2547 smb_panic (const char *why)
2549 const char *cmd = lp_panic_action ();
2550 if (cmd && *cmd)
2552 if (system (cmd))
2554 DEBUG (0, ("PANIC: cannot run panic handler command \"%s\"\n", cmd));
2557 DEBUG (0, ("PANIC: %s\n", why));
2558 dbgflush ();
2559 abort ();
2562 #if 0
2563 /*******************************************************************
2564 a readdir wrapper which just returns the file name
2565 ********************************************************************/
2566 char *
2567 readdirname (DIR * p)
2569 SMB_STRUCT_DIRENT *ptr;
2570 char *dname;
2572 if (!p)
2573 return (NULL);
2575 ptr = (SMB_STRUCT_DIRENT *) sys_readdir (p);
2576 if (!ptr)
2577 return (NULL);
2579 dname = ptr->d_name;
2581 #ifdef NEXT2
2582 if (telldir (p) < 0)
2583 return (NULL);
2584 #endif
2586 #ifdef HAVE_BROKEN_READDIR
2587 /* using /usr/ucb/cc is BAD */
2588 dname = dname - 2;
2589 #endif
2592 static pstring buf;
2593 memcpy (buf, dname, NAMLEN (ptr) + 1);
2594 dname = buf;
2597 return (dname);
2600 /*******************************************************************
2601 Utility function used to decide if the last component
2602 of a path matches a (possibly wildcarded) entry in a namelist.
2603 ********************************************************************/
2605 BOOL
2606 is_in_path (char *name, name_compare_entry * namelist)
2608 pstring last_component;
2609 char *p;
2611 DEBUG (8, ("is_in_path: %s\n", name));
2613 /* if we have no list it's obviously not in the path */
2614 if ((namelist == NULL) || ((namelist != NULL) && (namelist[0].name == NULL)))
2616 DEBUG (8, ("is_in_path: no name list.\n"));
2617 return False;
2620 /* Get the last component of the unix name. */
2621 p = strrchr (name, '/');
2622 strncpy (last_component, p ? ++p : name, sizeof (last_component) - 1);
2623 last_component[sizeof (last_component) - 1] = '\0';
2625 for (; namelist->name != NULL; namelist++)
2627 if (namelist->is_wild)
2630 * Look for a wildcard match. Use the old
2631 * 'unix style' mask match, rather than the
2632 * new NT one.
2634 if (unix_mask_match (last_component, namelist->name, case_sensitive, False))
2636 DEBUG (8, ("is_in_path: mask match succeeded\n"));
2637 return True;
2640 else
2642 if ((case_sensitive && (strcmp (last_component, namelist->name) == 0)) ||
2643 (!case_sensitive && (StrCaseCmp (last_component, namelist->name) == 0)))
2645 DEBUG (8, ("is_in_path: match succeeded\n"));
2646 return True;
2650 DEBUG (8, ("is_in_path: match not found\n"));
2652 return False;
2655 /*******************************************************************
2656 Strip a '/' separated list into an array of
2657 name_compare_enties structures suitable for
2658 passing to is_in_path(). We do this for
2659 speed so we can pre-parse all the names in the list
2660 and don't do it for each call to is_in_path().
2661 namelist is modified here and is assumed to be
2662 a copy owned by the caller.
2663 We also check if the entry contains a wildcard to
2664 remove a potentially expensive call to mask_match
2665 if possible.
2666 ********************************************************************/
2668 void
2669 set_namearray (name_compare_entry ** ppname_array, char *namelist)
2671 char *name_end;
2672 char *nameptr = namelist;
2673 int num_entries = 0;
2674 int i;
2676 (*ppname_array) = NULL;
2678 if ((nameptr == NULL) || ((nameptr != NULL) && (*nameptr == '\0')))
2679 return;
2681 /* We need to make two passes over the string. The
2682 first to count the number of elements, the second
2683 to split it.
2685 while (*nameptr)
2687 if (*nameptr == '/')
2689 /* cope with multiple (useless) /s) */
2690 nameptr++;
2691 continue;
2693 /* find the next / */
2694 name_end = strchr (nameptr, '/');
2696 /* oops - the last check for a / didn't find one. */
2697 if (name_end == NULL)
2698 break;
2700 /* next segment please */
2701 nameptr = name_end + 1;
2702 num_entries++;
2705 if (num_entries == 0)
2706 return;
2708 if (((*ppname_array) = (name_compare_entry *) malloc ((num_entries +
2709 1) * sizeof (name_compare_entry))) ==
2710 NULL)
2712 DEBUG (0, ("set_namearray: malloc fail\n"));
2713 return;
2716 /* Now copy out the names */
2717 nameptr = namelist;
2718 i = 0;
2719 while (*nameptr)
2721 if (*nameptr == '/')
2723 /* cope with multiple (useless) /s) */
2724 nameptr++;
2725 continue;
2727 /* find the next / */
2728 if ((name_end = strchr (nameptr, '/')) != NULL)
2730 *name_end = 0;
2733 /* oops - the last check for a / didn't find one. */
2734 if (name_end == NULL)
2735 break;
2737 (*ppname_array)[i].is_wild = ((strchr (nameptr, '?') != NULL) ||
2738 (strchr (nameptr, '*') != NULL));
2739 if (((*ppname_array)[i].name = strdup (nameptr)) == NULL)
2741 DEBUG (0, ("set_namearray: malloc fail (1)\n"));
2742 return;
2745 /* next segment please */
2746 nameptr = name_end + 1;
2747 i++;
2750 (*ppname_array)[i].name = NULL;
2752 return;
2755 /****************************************************************************
2756 routine to free a namearray.
2757 ****************************************************************************/
2759 void
2760 free_namearray (name_compare_entry * name_array)
2762 if (name_array == 0)
2763 return;
2765 if (name_array->name != NULL)
2766 free (name_array->name);
2768 free ((char *) name_array);
2771 /****************************************************************************
2772 routine to do file locking
2773 ****************************************************************************/
2774 BOOL
2775 fcntl_lock (int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
2777 #ifdef HAVE_FCNTL_LOCK
2778 SMB_STRUCT_FLOCK lock;
2779 int ret;
2781 if (lp_ole_locking_compat ())
2783 SMB_OFF_T mask2 = ((SMB_OFF_T) 0x3) << (SMB_OFF_T_BITS - 4);
2784 SMB_OFF_T mask = (mask2 << 2);
2786 /* make sure the count is reasonable, we might kill the lockd otherwise */
2787 count &= ~mask;
2789 /* the offset is often strange - remove 2 of its bits if either of
2790 the top two bits are set. Shift the top ones by two bits. This
2791 still allows OLE2 apps to operate, but should stop lockd from
2792 dieing */
2793 if ((offset & mask) != 0)
2794 offset = (offset & ~mask) | (((offset & mask) >> 2) & mask2);
2796 else
2798 SMB_OFF_T mask2 = ((SMB_OFF_T) 0x4) << (SMB_OFF_T_BITS - 4);
2799 SMB_OFF_T mask = (mask2 << 1);
2800 SMB_OFF_T neg_mask = ~mask;
2802 /* interpret negative counts as large numbers */
2803 if (count < 0)
2804 count &= ~mask;
2806 /* no negative offsets */
2807 if (offset < 0)
2808 offset &= ~mask;
2810 /* count + offset must be in range */
2811 while ((offset < 0 || (offset + count < 0)) && mask)
2813 offset &= ~mask;
2814 mask = ((mask >> 1) & neg_mask);
2818 DEBUG (8, ("fcntl_lock %d %d %.0f %.0f %d\n", fd, op, (double) offset, (double) count, type));
2820 lock.l_type = type;
2821 lock.l_whence = SEEK_SET;
2822 lock.l_start = offset;
2823 lock.l_len = count;
2824 lock.l_pid = 0;
2826 errno = 0;
2828 ret = fcntl (fd, op, &lock);
2829 if (errno == EFBIG)
2831 if (DEBUGLVL (0))
2833 dbgtext ("fcntl_lock: WARNING: lock request at offset %.0f, length %.0f returned\n",
2834 (double) offset, (double) count);
2835 dbgtext ("a 'file too large' error. This can happen when using 64 bit lock offsets\n");
2836 dbgtext
2837 ("on 32 bit NFS mounted file systems. Retrying with 32 bit truncated length.\n");
2839 /* 32 bit NFS file system, retry with smaller offset */
2840 errno = 0;
2841 lock.l_len = count & 0xffffffff;
2842 ret = fcntl (fd, op, &lock);
2845 if (errno != 0)
2846 DEBUG (3, ("fcntl lock gave errno %d (%s)\n", errno, unix_error_string (errno)));
2848 /* a lock query */
2849 if (op == SMB_F_GETLK)
2851 if ((ret != -1) &&
2852 (lock.l_type != F_UNLCK) && (lock.l_pid != 0) && (lock.l_pid != getpid ()))
2854 DEBUG (3, ("fd %d is locked by pid %d\n", fd, (int) lock.l_pid));
2855 return (True);
2858 /* it must be not locked or locked by me */
2859 return (False);
2862 /* a lock set or unset */
2863 if (ret == -1)
2865 DEBUG (3, ("lock failed at offset %.0f count %.0f op %d type %d (%s)\n",
2866 (double) offset, (double) count, op, type, unix_error_string (errno)));
2868 /* perhaps it doesn't support this sort of locking?? */
2869 if (errno == EINVAL)
2871 DEBUG (3, ("locking not supported? returning True\n"));
2872 return (True);
2875 return (False);
2878 /* everything went OK */
2879 DEBUG (8, ("Lock call successful\n"));
2881 return (True);
2882 #else
2883 return (False);
2884 #endif
2887 /*******************************************************************
2888 is the name specified one of my netbios names
2889 returns true is it is equal, false otherwise
2890 ********************************************************************/
2891 BOOL
2892 is_myname (char *s)
2894 int n;
2895 BOOL ret = False;
2897 for (n = 0; my_netbios_names[n]; n++)
2899 if (strequal (my_netbios_names[n], s))
2900 ret = True;
2902 DEBUG (8, ("is_myname(\"%s\") returns %d\n", s, ret));
2903 return (ret);
2905 #endif /* 0 */
2906 #if 0 /* Can be useful one day */
2907 /*******************************************************************
2908 set the horrid remote_arch string based on an enum.
2909 ********************************************************************/
2910 void
2911 set_remote_arch (enum remote_arch_types type)
2913 ra_type = type;
2914 switch (type)
2916 case RA_WFWG:
2917 remote_arch = "WfWg";
2918 return;
2919 case RA_OS2:
2920 remote_arch = "OS2";
2921 return;
2922 case RA_WIN95:
2923 remote_arch = "Win95";
2924 return;
2925 case RA_WINNT:
2926 remote_arch = "WinNT";
2927 return;
2928 case RA_SAMBA:
2929 remote_arch = "Samba";
2930 return;
2931 default:
2932 ra_type = RA_UNKNOWN;
2933 remote_arch = "UNKNOWN";
2934 break;
2938 /*******************************************************************
2939 Get the remote_arch type.
2940 ********************************************************************/
2941 enum remote_arch_types
2942 get_remote_arch (void)
2944 return ra_type;
2946 #endif /* 0 */
2947 #if 0
2948 /*******************************************************************
2949 align a pointer to a multiple of 2 bytes
2950 ********************************************************************/
2951 char *
2952 align2 (char *q, char *base)
2954 if ((q - base) & 1)
2956 q++;
2958 return q;
2961 void
2962 out_ascii (FILE * f, unsigned char *buf, int len)
2964 int i;
2965 for (i = 0; i < len; i++)
2967 fprintf (f, "%c", isprint (buf[i]) ? buf[i] : '.');
2971 void
2972 out_data (FILE * f, char *buf1, int len, int per_line)
2974 unsigned char *buf = (unsigned char *) buf1;
2975 int i = 0;
2976 if (len <= 0)
2978 return;
2981 fprintf (f, "[%03X] ", i);
2982 for (i = 0; i < len;)
2984 fprintf (f, "%02X ", (int) buf[i]);
2985 i++;
2986 if (i % (per_line / 2) == 0)
2987 fprintf (f, " ");
2988 if (i % per_line == 0)
2990 out_ascii (f, &buf[i - per_line], per_line / 2);
2991 fprintf (f, " ");
2992 out_ascii (f, &buf[i - per_line / 2], per_line / 2);
2993 fprintf (f, "\n");
2994 if (i < len)
2995 fprintf (f, "[%03X] ", i);
2998 if ((i % per_line) != 0)
3000 int n;
3002 n = per_line - (i % per_line);
3003 fprintf (f, " ");
3004 if (n > (per_line / 2))
3005 fprintf (f, " ");
3006 while (n--)
3008 fprintf (f, " ");
3010 n = MIN (per_line / 2, i % per_line);
3011 out_ascii (f, &buf[i - (i % per_line)], n);
3012 fprintf (f, " ");
3013 n = (i % per_line) - n;
3014 if (n > 0)
3015 out_ascii (f, &buf[i - n], n);
3016 fprintf (f, "\n");
3019 #endif /* 0 */
3021 void
3022 print_asc (int level, unsigned char *buf, int len)
3024 int i;
3025 for (i = 0; i < len; i++)
3026 DEBUG (level, ("%c", isprint (buf[i]) ? buf[i] : '.'));
3029 void
3030 dump_data (int level, char *buf1, int len)
3032 unsigned char *buf = (unsigned char *) buf1;
3033 int i = 0;
3034 if (len <= 0)
3035 return;
3037 DEBUG (level, ("[%03X] ", i));
3038 for (i = 0; i < len;)
3040 DEBUG (level, ("%02X ", (int) buf[i]));
3041 i++;
3042 if (i % 8 == 0)
3043 DEBUG (level, (" "));
3044 if (i % 16 == 0)
3046 print_asc (level, &buf[i - 16], 8);
3047 DEBUG (level, (" "));
3048 print_asc (level, &buf[i - 8], 8);
3049 DEBUG (level, ("\n"));
3050 if (i < len)
3051 DEBUG (level, ("[%03X] ", i));
3054 if (i % 16)
3056 int n;
3058 n = 16 - (i % 16);
3059 DEBUG (level, (" "));
3060 if (n > 8)
3061 DEBUG (level, (" "));
3062 while (n--)
3063 DEBUG (level, (" "));
3065 n = MIN (8, i % 16);
3066 print_asc (level, &buf[i - (i % 16)], n);
3067 DEBUG (level, (" "));
3068 n = (i % 16) - n;
3069 if (n > 0)
3070 print_asc (level, &buf[i - n], n);
3071 DEBUG (level, ("\n"));
3075 /*****************************************************************************
3076 * Provide a checksum on a string
3078 * Input: s - the null-terminated character string for which the checksum
3079 * will be calculated.
3081 * Output: The checksum value calculated for s.
3083 * ****************************************************************************
3086 str_checksum (const char *s)
3088 int res = 0;
3089 int c;
3090 int i = 0;
3092 while (*s)
3094 c = *s;
3095 res ^= (c << (i % 15)) ^ (c >> (15 - (i % 15)));
3096 s++;
3097 i++;
3099 return (res);
3100 } /* str_checksum */
3104 #if 0
3105 /*****************************************************************
3106 zero a memory area then free it. Used to catch bugs faster
3107 *****************************************************************/
3108 void
3109 zero_free (void *p, size_t size)
3111 memset (p, 0, size);
3112 free (p);
3116 /*****************************************************************
3117 set our open file limit to a requested max and return the limit
3118 *****************************************************************/
3120 set_maxfiles (int requested_max)
3122 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
3123 struct rlimit rlp;
3124 int saved_current_limit;
3126 if (getrlimit (RLIMIT_NOFILE, &rlp))
3128 DEBUG (0, ("set_maxfiles: getrlimit (1) for RLIMIT_NOFILE failed with error %s\n",
3129 unix_error_string (errno)));
3130 /* just guess... */
3131 return requested_max;
3135 * Set the fd limit to be real_max_open_files + MAX_OPEN_FUDGEFACTOR to
3136 * account for the extra fd we need
3137 * as well as the log files and standard
3138 * handles etc. Save the limit we want to set in case
3139 * we are running on an OS that doesn't support this limit (AIX)
3140 * which always returns RLIM_INFINITY for rlp.rlim_max.
3143 saved_current_limit = rlp.rlim_cur = MIN (requested_max, rlp.rlim_max);
3145 if (setrlimit (RLIMIT_NOFILE, &rlp))
3147 DEBUG (0, ("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d files failed with error %s\n",
3148 (int) rlp.rlim_cur, unix_error_string (errno)));
3149 /* just guess... */
3150 return saved_current_limit;
3153 if (getrlimit (RLIMIT_NOFILE, &rlp))
3155 DEBUG (0, ("set_maxfiles: getrlimit (2) for RLIMIT_NOFILE failed with error %s\n",
3156 unix_error_string (errno)));
3157 /* just guess... */
3158 return saved_current_limit;
3161 #if defined(RLIM_INFINITY)
3162 if (rlp.rlim_cur == RLIM_INFINITY)
3163 return saved_current_limit;
3164 #endif
3166 if ((int) rlp.rlim_cur > saved_current_limit)
3167 return saved_current_limit;
3169 return rlp.rlim_cur;
3170 #else /* !defined(HAVE_GETRLIMIT) || !defined(RLIMIT_NOFILE) */
3172 * No way to know - just guess...
3174 return requested_max;
3175 #endif
3177 #endif /* 0 */