* samba/lib/util_str.c: Comment out strhasupper(), strhaslower(),
[midnight-commander.git] / vfs / samba / lib / util.c
blob03e67c71394380b613114fff8b1070bf27015ab9
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 Samba utility functions
5 Copyright (C) Andrew Tridgell 1992-1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "includes.h"
24 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
25 #ifdef WITH_NISPLUS_HOME
26 #ifdef BROKEN_NISPLUS_INCLUDE_FILES
28 * The following lines are needed due to buggy include files
29 * in Solaris 2.6 which define GROUP in both /usr/include/sys/acl.h and
30 * also in /usr/include/rpcsvc/nis.h. The definitions conflict. JRA.
31 * Also GROUP_OBJ is defined as 0x4 in /usr/include/sys/acl.h and as
32 * an enum in /usr/include/rpcsvc/nis.h.
35 #if defined(GROUP)
36 #undef GROUP
37 #endif
39 #if defined(GROUP_OBJ)
40 #undef GROUP_OBJ
41 #endif
43 #endif /* BROKEN_NISPLUS_INCLUDE_FILES */
45 #include <rpcsvc/nis.h>
47 #else /* !WITH_NISPLUS_HOME */
49 #include "rpcsvc/ypclnt.h"
51 #endif /* WITH_NISPLUS_HOME */
52 #endif /* HAVE_NETGROUP && WITH_AUTOMOUNT */
54 #ifdef WITH_SSL
55 #include <ssl.h>
56 #undef Realloc /* SSLeay defines this and samba has a function of this name */
57 extern SSL *ssl;
58 extern int sslFd;
59 #endif /* WITH_SSL */
61 extern int DEBUGLEVEL;
62 #if 0
63 int Protocol = PROTOCOL_COREPLUS;
64 #endif /*0 */
66 /* a default finfo structure to ensure all fields are sensible */
67 file_info const def_finfo = {-1,0,0,0,0,0,0,""};
69 /* the client file descriptor */
70 extern int Client;
72 /* this is used by the chaining code */
73 const int chain_size = 0;
74 #if 0
75 int trans_num = 0;
76 #endif /*0 */
79 case handling on filenames
81 const int case_default = CASE_LOWER;
83 #if 0
84 /* the following control case operations - they are put here so the
85 client can link easily */
86 BOOL case_sensitive;
87 BOOL case_preserve;
88 BOOL use_mangled_map = False;
89 BOOL short_case_preserve;
90 BOOL case_mangle;
91 #endif /*0 */
93 static const char *remote_machine = "";
94 static const char *local_machine = "";
95 static const char *remote_arch = "UNKNOWN";
96 #if 0
97 static enum remote_arch_types ra_type = RA_UNKNOWN;
98 #endif
99 static const char *remote_proto = "UNKNOWN";
100 pstring myhostname="";
101 pstring user_socket_options="";
103 pstring sesssetup_user="";
104 static char * const samlogon_user = "";
106 const BOOL sam_logon_in_ssb = False;
108 pstring global_myname = "";
109 #if 0
110 char **my_netbios_names;
111 #endif /*0 */
114 /****************************************************************************
115 find a suitable temporary directory. The result should be copied immediately
116 as it may be overwritten by a subsequent call
117 ****************************************************************************/
118 char *tmpdir(void)
120 char *p;
121 if ((p = getenv("MC_TMPDIR")) || (p = getenv("TMPDIR"))) {
122 return p;
124 return "/tmp";
127 /****************************************************************************
128 determine whether we are in the specified group
129 ****************************************************************************/
130 #if 0
131 BOOL in_group(gid_t group, gid_t current_gid, int ngroups, gid_t *groups)
133 int i;
135 if (group == current_gid) return(True);
137 for (i=0;i<ngroups;i++)
138 if (group == groups[i])
139 return(True);
141 return(False);
145 /****************************************************************************
146 like atoi but gets the value up to the separater character
147 ****************************************************************************/
148 char *Atoic(char *p, int *n, char *c)
150 if (!isdigit((int)*p))
152 DEBUG(5, ("Atoic: malformed number\n"));
153 return NULL;
156 (*n) = atoi(p);
158 while ((*p) && isdigit((int)*p))
160 p++;
163 if (strchr(c, *p) == NULL)
165 DEBUG(5, ("Atoic: no separator characters (%s) not found\n", c));
166 return NULL;
169 return p;
172 /*************************************************************************
173 reads a list of numbers
174 *************************************************************************/
175 char *get_numlist(char *p, uint32 **num, int *count)
177 int val;
179 if (num == NULL || count == NULL)
181 return NULL;
184 (*count) = 0;
185 (*num ) = NULL;
187 while ((p = Atoic(p, &val, ":,")) != NULL && (*p) != ':')
189 (*num) = Realloc((*num), ((*count)+1) * sizeof(uint32));
190 if ((*num) == NULL)
192 return NULL;
194 (*num)[(*count)] = val;
195 (*count)++;
196 p++;
199 return p;
201 #endif /* 0 */
202 /*******************************************************************
203 copy an IP address from one buffer to another
204 ********************************************************************/
205 void putip(void *dest,void *src)
207 memcpy(dest,src,4);
211 #define TRUNCATE_NETBIOS_NAME 1
212 #if 0
213 /*******************************************************************
214 convert, possibly using a stupid microsoft-ism which has destroyed
215 the transport independence of netbios (for CIFS vendors that usually
216 use the Win95-type methods, not for NT to NT communication, which uses
217 DCE/RPC and therefore full-length unicode strings...) a dns name into
218 a netbios name.
220 the netbios name (NOT necessarily null-terminated) is truncated to 15
221 characters.
223 ******************************************************************/
224 char *dns_to_netbios_name(char *dns_name)
226 static char netbios_name[16];
227 int i;
228 StrnCpy(netbios_name, dns_name, 15);
229 netbios_name[15] = 0;
231 #ifdef TRUNCATE_NETBIOS_NAME
232 /* ok. this is because of a stupid microsoft-ism. if the called host
233 name contains a '.', microsoft clients expect you to truncate the
234 netbios name up to and including the '.' this even applies, by
235 mistake, to workgroup (domain) names, which is _really_ daft.
237 for (i = 15; i >= 0; i--)
239 if (netbios_name[i] == '.')
241 netbios_name[i] = 0;
242 break;
245 #endif /* TRUNCATE_NETBIOS_NAME */
247 return netbios_name;
251 /****************************************************************************
252 interpret the weird netbios "name". Return the name type
253 ****************************************************************************/
254 static int name_interpret(char *in,char *out)
256 int ret;
257 int len = (*in++) / 2;
259 *out=0;
261 if (len > 30 || len<1) return(0);
263 while (len--)
265 if (in[0] < 'A' || in[0] > 'P' || in[1] < 'A' || in[1] > 'P') {
266 *out = 0;
267 return(0);
269 *out = ((in[0]-'A')<<4) + (in[1]-'A');
270 in += 2;
271 out++;
273 *out = 0;
274 ret = out[-1];
276 #ifdef NETBIOS_SCOPE
277 /* Handle any scope names */
278 while(*in)
280 *out++ = '.'; /* Scope names are separated by periods */
281 len = *(unsigned char *)in++;
282 StrnCpy(out, in, len);
283 out += len;
284 *out=0;
285 in += len;
287 #endif
288 return(ret);
290 #endif /* 0 */
292 /****************************************************************************
293 mangle a name into netbios format
295 Note: <Out> must be (33 + strlen(scope) + 2) bytes long, at minimum.
296 ****************************************************************************/
297 int name_mangle( char *In, char *Out, char name_type )
299 int i;
300 int c;
301 int len;
302 char buf[20];
303 char *p = Out;
304 extern pstring global_scope;
306 /* Safely copy the input string, In, into buf[]. */
307 (void)memset( buf, 0, 20 );
308 if (strcmp(In,"*") == 0)
309 buf[0] = '*';
310 else
311 (void)slprintf( buf, sizeof(buf) - 1, "%-15.15s%c", In, name_type );
313 /* Place the length of the first field into the output buffer. */
314 p[0] = 32;
315 p++;
317 /* Now convert the name to the rfc1001/1002 format. */
318 for( i = 0; i < 16; i++ )
320 c = toupper( buf[i] );
321 p[i*2] = ( (c >> 4) & 0x000F ) + 'A';
322 p[(i*2)+1] = (c & 0x000F) + 'A';
324 p += 32;
325 p[0] = '\0';
327 /* Add the scope string. */
328 for( i = 0, len = 0; NULL != global_scope; i++, len++ )
330 switch( global_scope[i] )
332 case '\0':
333 p[0] = len;
334 if( len > 0 )
335 p[len+1] = 0;
336 return( name_len(Out) );
337 case '.':
338 p[0] = len;
339 p += (len + 1);
340 len = -1;
341 break;
342 default:
343 p[len+1] = global_scope[i];
344 break;
348 return( name_len(Out) );
349 } /* name_mangle */
351 /*******************************************************************
352 check if a file exists
353 ********************************************************************/
354 BOOL file_exist(char *fname,SMB_STRUCT_STAT *sbuf)
356 SMB_STRUCT_STAT st;
357 if (!sbuf) sbuf = &st;
359 if (sys_stat(fname,sbuf) != 0)
360 return(False);
362 return(S_ISREG(sbuf->st_mode));
365 /*******************************************************************
366 check a files mod time
367 ********************************************************************/
368 time_t file_modtime(char *fname)
370 SMB_STRUCT_STAT st;
372 if (sys_stat(fname,&st) != 0)
373 return(0);
375 return(st.st_mtime);
377 #if 0
378 /*******************************************************************
379 check if a directory exists
380 ********************************************************************/
381 BOOL directory_exist(char *dname,SMB_STRUCT_STAT *st)
383 SMB_STRUCT_STAT st2;
384 BOOL ret;
386 if (!st) st = &st2;
388 if (sys_stat(dname,st) != 0)
389 return(False);
391 ret = S_ISDIR(st->st_mode);
392 if(!ret)
393 errno = ENOTDIR;
394 return ret;
397 /*******************************************************************
398 returns the size in bytes of the named file
399 ********************************************************************/
400 SMB_OFF_T file_size(char *file_name)
402 SMB_STRUCT_STAT buf;
403 buf.st_size = 0;
404 if(sys_stat(file_name,&buf) != 0)
405 return (SMB_OFF_T)-1;
406 return(buf.st_size);
408 #endif /* 0 */
410 /*******************************************************************
411 return a string representing an attribute for a file
412 ********************************************************************/
413 char *attrib_string(uint16 mode)
415 static fstring attrstr;
417 attrstr[0] = 0;
419 if (mode & aVOLID) fstrcat(attrstr,"V");
420 if (mode & aDIR) fstrcat(attrstr,"D");
421 if (mode & aARCH) fstrcat(attrstr,"A");
422 if (mode & aHIDDEN) fstrcat(attrstr,"H");
423 if (mode & aSYSTEM) fstrcat(attrstr,"S");
424 if (mode & aRONLY) fstrcat(attrstr,"R");
426 return(attrstr);
429 #if 0
430 /****************************************************************************
431 make a file into unix format
432 ****************************************************************************/
433 void unix_format(char *fname)
435 string_replace(fname,'\\','/');
438 /****************************************************************************
439 make a file into dos format
440 ****************************************************************************/
441 void dos_format(char *fname)
443 string_replace(fname,'/','\\');
445 #endif /* 0 */
446 /*******************************************************************
447 show a smb message structure
448 ********************************************************************/
449 void show_msg(char *buf)
451 int i;
452 int bcc=0;
454 if (DEBUGLEVEL < 5) return;
456 DEBUG(5,("size=%d\nsmb_com=0x%x\nsmb_rcls=%d\nsmb_reh=%d\nsmb_err=%d\nsmb_flg=%d\nsmb_flg2=%d\n",
457 smb_len(buf),
458 (int)CVAL(buf,smb_com),
459 (int)CVAL(buf,smb_rcls),
460 (int)CVAL(buf,smb_reh),
461 (int)SVAL(buf,smb_err),
462 (int)CVAL(buf,smb_flg),
463 (int)SVAL(buf,smb_flg2)));
464 DEBUG(5,("smb_tid=%d\nsmb_pid=%d\nsmb_uid=%d\nsmb_mid=%d\nsmt_wct=%d\n",
465 (int)SVAL(buf,smb_tid),
466 (int)SVAL(buf,smb_pid),
467 (int)SVAL(buf,smb_uid),
468 (int)SVAL(buf,smb_mid),
469 (int)CVAL(buf,smb_wct)));
471 for (i=0;i<(int)CVAL(buf,smb_wct);i++)
473 DEBUG(5,("smb_vwv[%d]=%d (0x%X)\n",i,
474 SVAL(buf,smb_vwv+2*i),SVAL(buf,smb_vwv+2*i)));
477 bcc = (int)SVAL(buf,smb_vwv+2*(CVAL(buf,smb_wct)));
479 DEBUG(5,("smb_bcc=%d\n",bcc));
481 if (DEBUGLEVEL < 10) return;
483 if (DEBUGLEVEL < 50)
485 bcc = MIN(bcc, 512);
488 dump_data(10, smb_buf(buf), bcc);
490 /*******************************************************************
491 return the length of an smb packet
492 ********************************************************************/
493 int smb_len(char *buf)
495 return( PVAL(buf,3) | (PVAL(buf,2)<<8) | ((PVAL(buf,1)&1)<<16) );
498 /*******************************************************************
499 set the length of an smb packet
500 ********************************************************************/
501 void _smb_setlen(char *buf,int len)
503 buf[0] = 0;
504 buf[1] = (len&0x10000)>>16;
505 buf[2] = (len&0xFF00)>>8;
506 buf[3] = len&0xFF;
509 /*******************************************************************
510 set the length and marker of an smb packet
511 ********************************************************************/
512 void smb_setlen(char *buf,int len)
514 _smb_setlen(buf,len);
516 CVAL(buf,4) = 0xFF;
517 CVAL(buf,5) = 'S';
518 CVAL(buf,6) = 'M';
519 CVAL(buf,7) = 'B';
522 /*******************************************************************
523 setup the word count and byte count for a smb message
524 ********************************************************************/
525 int set_message(char *buf,int num_words,int num_bytes,BOOL zero)
527 if (zero)
528 memset(buf + smb_size,'\0',num_words*2 + num_bytes);
529 CVAL(buf,smb_wct) = num_words;
530 SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
531 smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
532 return (smb_size + num_words*2 + num_bytes);
535 /*******************************************************************
536 return the number of smb words
537 ********************************************************************/
538 static int smb_numwords(char *buf)
540 return (CVAL(buf,smb_wct));
543 /*******************************************************************
544 return the size of the smb_buf region of a message
545 ********************************************************************/
546 int smb_buflen(char *buf)
548 return(SVAL(buf,smb_vwv0 + smb_numwords(buf)*2));
551 /*******************************************************************
552 return a pointer to the smb_buf data area
553 ********************************************************************/
554 static int smb_buf_ofs(char *buf)
556 return (smb_size + CVAL(buf,smb_wct)*2);
559 /*******************************************************************
560 return a pointer to the smb_buf data area
561 ********************************************************************/
562 char *smb_buf(char *buf)
564 return (buf + smb_buf_ofs(buf));
567 /*******************************************************************
568 return the SMB offset into an SMB buffer
569 ********************************************************************/
570 int smb_offset(char *p,char *buf)
572 return(PTR_DIFF(p,buf+4) + chain_size);
575 #if 0
576 /*******************************************************************
577 reduce a file name, removing .. elements.
578 ********************************************************************/
579 void dos_clean_name(char *s)
581 char *p=NULL;
583 DEBUG(3,("dos_clean_name [%s]\n",s));
585 /* remove any double slashes */
586 string_sub(s, "\\\\", "\\");
588 while ((p = strstr(s,"\\..\\")) != NULL)
590 pstring s1;
592 *p = 0;
593 pstrcpy(s1,p+3);
595 if ((p=strrchr(s,'\\')) != NULL)
596 *p = 0;
597 else
598 *s = 0;
599 pstrcat(s,s1);
602 trim_string(s,NULL,"\\..");
604 string_sub(s, "\\.\\", "\\");
607 /*******************************************************************
608 reduce a file name, removing .. elements.
609 ********************************************************************/
610 void unix_clean_name(char *s)
612 char *p=NULL;
614 DEBUG(3,("unix_clean_name [%s]\n",s));
616 /* remove any double slashes */
617 string_sub(s, "//","/");
619 /* Remove leading ./ characters */
620 if(strncmp(s, "./", 2) == 0) {
621 trim_string(s, "./", NULL);
622 if(*s == 0)
623 pstrcpy(s,"./");
626 while ((p = strstr(s,"/../")) != NULL)
628 pstring s1;
630 *p = 0;
631 pstrcpy(s1,p+3);
633 if ((p=strrchr(s,'/')) != NULL)
634 *p = 0;
635 else
636 *s = 0;
637 pstrcat(s,s1);
640 trim_string(s,NULL,"/..");
643 /*******************************************************************
644 reduce a file name, removing .. elements and checking that
645 it is below dir in the heirachy. This uses dos_GetWd() and so must be run
646 on the system that has the referenced file system.
648 widelinks are allowed if widelinks is true
649 ********************************************************************/
650 BOOL reduce_name(char *s,char *dir,BOOL widelinks)
652 #ifndef REDUCE_PATHS
653 return True;
654 #else
655 pstring dir2;
656 pstring wd;
657 pstring base_name;
658 pstring newname;
659 char *p=NULL;
660 BOOL relative = (*s != '/');
662 *dir2 = *wd = *base_name = *newname = 0;
664 if (widelinks)
666 unix_clean_name(s);
667 /* can't have a leading .. */
668 if (strncmp(s,"..",2) == 0 && (s[2]==0 || s[2]=='/'))
670 DEBUG(3,("Illegal file name? (%s)\n",s));
671 return(False);
674 if (strlen(s) == 0)
675 pstrcpy(s,"./");
677 return(True);
680 DEBUG(3,("reduce_name [%s] [%s]\n",s,dir));
682 /* remove any double slashes */
683 string_sub(s,"//","/");
685 pstrcpy(base_name,s);
686 p = strrchr(base_name,'/');
688 if (!p)
689 return(True);
691 if (!dos_GetWd(wd))
693 DEBUG(0,("couldn't getwd for %s %s\n",s,dir));
694 return(False);
697 if (dos_ChDir(dir) != 0)
699 DEBUG(0,("couldn't chdir to %s\n",dir));
700 return(False);
703 if (!dos_GetWd(dir2))
705 DEBUG(0,("couldn't getwd for %s\n",dir));
706 dos_ChDir(wd);
707 return(False);
710 if (p && (p != base_name))
712 *p = 0;
713 if (strcmp(p+1,".")==0)
714 p[1]=0;
715 if (strcmp(p+1,"..")==0)
716 *p = '/';
719 if (dos_ChDir(base_name) != 0)
721 dos_ChDir(wd);
722 DEBUG(3,("couldn't chdir for %s %s basename=%s\n",s,dir,base_name));
723 return(False);
726 if (!dos_GetWd(newname))
728 dos_ChDir(wd);
729 DEBUG(2,("couldn't get wd for %s %s\n",s,dir2));
730 return(False);
733 if (p && (p != base_name))
735 pstrcat(newname,"/");
736 pstrcat(newname,p+1);
740 size_t l = strlen(dir2);
741 if (dir2[l-1] == '/')
742 l--;
744 if (strncmp(newname,dir2,l) != 0)
746 dos_ChDir(wd);
747 DEBUG(2,("Bad access attempt? s=%s dir=%s newname=%s l=%d\n",s,dir2,newname,(int)l));
748 return(False);
751 if (relative)
753 if (newname[l] == '/')
754 pstrcpy(s,newname + l + 1);
755 else
756 pstrcpy(s,newname+l);
758 else
759 pstrcpy(s,newname);
762 dos_ChDir(wd);
764 if (strlen(s) == 0)
765 pstrcpy(s,"./");
767 DEBUG(3,("reduced to %s\n",s));
768 return(True);
769 #endif
773 /****************************************************************************
774 expand some *s
775 ****************************************************************************/
776 static void expand_one(char *Mask,int len)
778 char *p1;
779 while ((p1 = strchr(Mask,'*')) != NULL)
781 int lfill = (len+1) - strlen(Mask);
782 int l1= (p1 - Mask);
783 pstring tmp;
784 pstrcpy(tmp,Mask);
785 memset(tmp+l1,'?',lfill);
786 pstrcpy(tmp + l1 + lfill,Mask + l1 + 1);
787 pstrcpy(Mask,tmp);
791 /****************************************************************************
792 parse out a directory name from a path name. Assumes dos style filenames.
793 ****************************************************************************/
794 static void dirname_dos(char *path,char *buf)
796 split_at_last_component(path, buf, '\\', NULL);
800 /****************************************************************************
801 parse out a filename from a path name. Assumes dos style filenames.
802 ****************************************************************************/
803 static char *filename_dos(char *path,char *buf)
805 char *p = strrchr(path,'\\');
807 if (!p)
808 pstrcpy(buf,path);
809 else
810 pstrcpy(buf,p+1);
812 return(buf);
815 /****************************************************************************
816 expand a wildcard expression, replacing *s with ?s
817 ****************************************************************************/
818 void expand_mask(char *Mask,BOOL doext)
820 pstring mbeg,mext;
821 pstring dirpart;
822 pstring filepart;
823 BOOL hasdot = False;
824 char *p1;
825 BOOL absolute = (*Mask == '\\');
827 *mbeg = *mext = *dirpart = *filepart = 0;
829 /* parse the directory and filename */
830 if (strchr(Mask,'\\'))
831 dirname_dos(Mask,dirpart);
833 filename_dos(Mask,filepart);
835 pstrcpy(mbeg,filepart);
836 if ((p1 = strchr(mbeg,'.')) != NULL)
838 hasdot = True;
839 *p1 = 0;
840 p1++;
841 pstrcpy(mext,p1);
843 else
845 pstrcpy(mext,"");
846 if (strlen(mbeg) > 8)
848 pstrcpy(mext,mbeg + 8);
849 mbeg[8] = 0;
853 if (*mbeg == 0)
854 pstrcpy(mbeg,"????????");
855 if ((*mext == 0) && doext && !hasdot)
856 pstrcpy(mext,"???");
858 if (strequal(mbeg,"*") && *mext==0)
859 pstrcpy(mext,"*");
861 /* expand *'s */
862 expand_one(mbeg,8);
863 if (*mext)
864 expand_one(mext,3);
866 pstrcpy(Mask,dirpart);
867 if (*dirpart || absolute) pstrcat(Mask,"\\");
868 pstrcat(Mask,mbeg);
869 pstrcat(Mask,".");
870 pstrcat(Mask,mext);
872 DEBUG(6,("Mask expanded to [%s]\n",Mask));
876 /****************************************************************************
877 make a dir struct
878 ****************************************************************************/
879 void make_dir_struct(char *buf,char *mask,char *fname,SMB_OFF_T size,int mode,time_t date)
881 char *p;
882 pstring mask2;
884 pstrcpy(mask2,mask);
886 if ((mode & aDIR) != 0)
887 size = 0;
889 memset(buf+1,' ',11);
890 if ((p = strchr(mask2,'.')) != NULL)
892 *p = 0;
893 memcpy(buf+1,mask2,MIN(strlen(mask2),8));
894 memcpy(buf+9,p+1,MIN(strlen(p+1),3));
895 *p = '.';
897 else
898 memcpy(buf+1,mask2,MIN(strlen(mask2),11));
900 memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
901 CVAL(buf,21) = mode;
902 put_dos_date(buf,22,date);
903 SSVAL(buf,26,size & 0xFFFF);
904 SSVAL(buf,28,(size >> 16)&0xFFFF);
905 StrnCpy(buf+30,fname,12);
906 if (!case_sensitive)
907 strupper(buf+30);
908 DEBUG(8,("put name [%s] into dir struct\n",buf+30));
912 /*******************************************************************
913 close the low 3 fd's and open dev/null in their place
914 ********************************************************************/
915 void close_low_fds(void)
917 int fd;
918 int i;
919 close(0); close(1); close(2);
920 /* try and use up these file descriptors, so silly
921 library routines writing to stdout etc won't cause havoc */
922 for (i=0;i<3;i++) {
923 fd = sys_open("/dev/null",O_RDWR,0);
924 if (fd < 0) fd = sys_open("/dev/null",O_WRONLY,0);
925 if (fd < 0) {
926 DEBUG(0,("Cannot open /dev/null\n"));
927 return;
929 if (fd != i) {
930 DEBUG(0,("Didn't get file descriptor %d\n",i));
931 return;
935 #endif /* 0 */
937 /****************************************************************************
938 Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
939 else
940 if SYSV use O_NDELAY
941 if BSD use FNDELAY
942 ****************************************************************************/
943 int set_blocking(int fd, BOOL set)
945 int val;
946 #ifdef O_NONBLOCK
947 #define FLAG_TO_SET O_NONBLOCK
948 #else
949 #ifdef SYSV
950 #define FLAG_TO_SET O_NDELAY
951 #else /* BSD */
952 #define FLAG_TO_SET FNDELAY
953 #endif
954 #endif
956 if((val = fcntl(fd, F_GETFL, 0)) == -1)
957 return -1;
958 if(set) /* Turn blocking on - ie. clear nonblock flag */
959 val &= ~FLAG_TO_SET;
960 else
961 val |= FLAG_TO_SET;
962 return fcntl( fd, F_SETFL, val);
963 #undef FLAG_TO_SET
967 /*******************************************************************
968 find the difference in milliseconds between two struct timeval
969 values
970 ********************************************************************/
971 int TvalDiff(struct timeval *tvalold,struct timeval *tvalnew)
973 return((tvalnew->tv_sec - tvalold->tv_sec)*1000 +
974 ((int)tvalnew->tv_usec - (int)tvalold->tv_usec)/1000);
978 #if 0
979 /****************************************************************************
980 transfer some data between two fd's
981 ****************************************************************************/
982 SMB_OFF_T transfer_file(int infd,int outfd,SMB_OFF_T n,char *header,int headlen,int align)
984 static char *buf=NULL;
985 static int size=0;
986 char *buf1,*abuf;
987 SMB_OFF_T total = 0;
989 DEBUG(4,("transfer_file n=%.0f (head=%d) called\n",(double)n,headlen));
991 if (size == 0) {
992 size = lp_readsize();
993 size = MAX(size,1024);
996 while (!buf && size>0) {
997 buf = (char *)Realloc(buf,size+8);
998 if (!buf) size /= 2;
1001 if (!buf) {
1002 DEBUG(0,("Cannot allocate transfer buffer!\n"));
1003 exit(1);
1006 abuf = buf + (align%8);
1008 if (header)
1009 n += headlen;
1011 while (n > 0)
1013 int s = (int)MIN(n,(SMB_OFF_T)size);
1014 int ret,ret2=0;
1016 ret = 0;
1018 if (header && (headlen >= MIN(s,1024))) {
1019 buf1 = header;
1020 s = headlen;
1021 ret = headlen;
1022 headlen = 0;
1023 header = NULL;
1024 } else {
1025 buf1 = abuf;
1028 if (header && headlen > 0)
1030 ret = MIN(headlen,size);
1031 memcpy(buf1,header,ret);
1032 headlen -= ret;
1033 header += ret;
1034 if (headlen <= 0) header = NULL;
1037 if (s > ret)
1038 ret += read(infd,buf1+ret,s-ret);
1040 if (ret > 0)
1042 ret2 = (outfd>=0?write_data(outfd,buf1,ret):ret);
1043 if (ret2 > 0) total += ret2;
1044 /* if we can't write then dump excess data */
1045 if (ret2 != ret)
1046 transfer_file(infd,-1,n-(ret+headlen),NULL,0,0);
1048 if (ret <= 0 || ret2 != ret)
1049 return(total);
1050 n -= ret;
1052 return(total);
1056 /****************************************************************************
1057 find a pointer to a netbios name
1058 ****************************************************************************/
1059 static char *name_ptr(char *buf,int ofs)
1061 unsigned char c = *(unsigned char *)(buf+ofs);
1063 if ((c & 0xC0) == 0xC0)
1065 uint16 l;
1066 char p[2];
1067 memcpy(p,buf+ofs,2);
1068 p[0] &= ~0xC0;
1069 l = RSVAL(p,0);
1070 DEBUG(5,("name ptr to pos %d from %d is %s\n",l,ofs,buf+l));
1071 return(buf + l);
1073 else
1074 return(buf+ofs);
1077 /****************************************************************************
1078 extract a netbios name from a buf
1079 ****************************************************************************/
1080 int name_extract(char *buf,int ofs,char *name)
1082 char *p = name_ptr(buf,ofs);
1083 int d = PTR_DIFF(p,buf+ofs);
1084 pstrcpy(name,"");
1085 if (d < -50 || d > 50) return(0);
1086 return(name_interpret(p,name));
1088 #endif /* 0 */
1090 /****************************************************************************
1091 return the total storage length of a mangled name
1092 ****************************************************************************/
1093 int name_len(char *s1)
1095 /* NOTE: this argument _must_ be unsigned */
1096 unsigned char *s = (unsigned char *)s1;
1097 int len;
1099 /* If the two high bits of the byte are set, return 2. */
1100 if (0xC0 == (*s & 0xC0))
1101 return(2);
1103 /* Add up the length bytes. */
1104 for (len = 1; (*s); s += (*s) + 1) {
1105 len += *s + 1;
1106 SMB_ASSERT(len < 80);
1109 return(len);
1110 } /* name_len */
1113 /*******************************************************************
1114 sleep for a specified number of milliseconds
1115 ********************************************************************/
1116 void msleep(int t)
1118 int tdiff=0;
1119 struct timeval tval,t1,t2;
1120 fd_set fds;
1122 GetTimeOfDay(&t1);
1123 GetTimeOfDay(&t2);
1125 while (tdiff < t) {
1126 tval.tv_sec = (t-tdiff)/1000;
1127 tval.tv_usec = 1000*((t-tdiff)%1000);
1129 FD_ZERO(&fds);
1130 errno = 0;
1131 sys_select(0,&fds,&tval);
1133 GetTimeOfDay(&t2);
1134 tdiff = TvalDiff(&t1,&t2);
1138 #if 0
1139 /*********************************************************
1140 * Recursive routine that is called by unix_mask_match.
1141 * Does the actual matching. This is the 'original code'
1142 * used by the unix matcher.
1143 *********************************************************/
1144 static BOOL unix_do_match(char *str, char *regexp, int case_sig)
1146 char *p;
1148 for( p = regexp; *p && *str; ) {
1149 switch(*p) {
1150 case '?':
1151 str++; p++;
1152 break;
1154 case '*':
1155 /* Look for a character matching
1156 the one after the '*' */
1157 p++;
1158 if(!*p)
1159 return True; /* Automatic match */
1160 while(*str) {
1161 while(*str && (case_sig ? (*p != *str) : (toupper(*p)!=toupper(*str))))
1162 str++;
1163 if(unix_do_match(str,p,case_sig))
1164 return True;
1165 if(!*str)
1166 return False;
1167 else
1168 str++;
1170 return False;
1172 default:
1173 if(case_sig) {
1174 if(*str != *p)
1175 return False;
1176 } else {
1177 if(toupper(*str) != toupper(*p))
1178 return False;
1180 str++, p++;
1181 break;
1184 if(!*p && !*str)
1185 return True;
1187 if (!*p && str[0] == '.' && str[1] == 0)
1188 return(True);
1190 if (!*str && *p == '?')
1192 while (*p == '?') p++;
1193 return(!*p);
1196 if(!*str && (*p == '*' && p[1] == '\0'))
1197 return True;
1198 return False;
1202 /*********************************************************
1203 * Routine to match a given string with a regexp - uses
1204 * simplified regexp that takes * and ? only. Case can be
1205 * significant or not.
1206 * This is the 'original code' used by the unix matcher.
1207 *********************************************************/
1209 static BOOL unix_mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
1211 char *p;
1212 pstring p1, p2;
1213 fstring ebase,eext,sbase,sext;
1215 BOOL matched;
1217 /* Make local copies of str and regexp */
1218 StrnCpy(p1,regexp,sizeof(pstring)-1);
1219 StrnCpy(p2,str,sizeof(pstring)-1);
1221 if (!strchr(p2,'.')) {
1222 pstrcat(p2,".");
1225 /* Remove any *? and ** as they are meaningless */
1226 for(p = p1; *p; p++)
1227 while( *p == '*' && (p[1] == '?' ||p[1] == '*'))
1228 (void)pstrcpy( &p[1], &p[2]);
1230 if (strequal(p1,"*")) return(True);
1232 DEBUG(8,("unix_mask_match str=<%s> regexp=<%s>, case_sig = %d\n", p2, p1, case_sig));
1234 if (trans2) {
1235 fstrcpy(ebase,p1);
1236 fstrcpy(sbase,p2);
1237 } else {
1238 if ((p=strrchr(p1,'.'))) {
1239 *p = 0;
1240 fstrcpy(ebase,p1);
1241 fstrcpy(eext,p+1);
1242 } else {
1243 fstrcpy(ebase,p1);
1244 eext[0] = 0;
1247 if (!strequal(p2,".") && !strequal(p2,"..") && (p=strrchr(p2,'.'))) {
1248 *p = 0;
1249 fstrcpy(sbase,p2);
1250 fstrcpy(sext,p+1);
1251 } else {
1252 fstrcpy(sbase,p2);
1253 fstrcpy(sext,"");
1257 matched = unix_do_match(sbase,ebase,case_sig) &&
1258 (trans2 || unix_do_match(sext,eext,case_sig));
1260 DEBUG(8,("unix_mask_match returning %d\n", matched));
1262 return matched;
1265 /*********************************************************
1266 * Recursive routine that is called by mask_match.
1267 * Does the actual matching. Returns True if matched,
1268 * False if failed. This is the 'new' NT style matcher.
1269 *********************************************************/
1271 BOOL do_match(char *str, char *regexp, int case_sig)
1273 char *p;
1275 for( p = regexp; *p && *str; ) {
1276 switch(*p) {
1277 case '?':
1278 str++; p++;
1279 break;
1281 case '*':
1282 /* Look for a character matching
1283 the one after the '*' */
1284 p++;
1285 if(!*p)
1286 return True; /* Automatic match */
1287 while(*str) {
1288 while(*str && (case_sig ? (*p != *str) : (toupper(*p)!=toupper(*str))))
1289 str++;
1290 /* Now eat all characters that match, as
1291 we want the *last* character to match. */
1292 while(*str && (case_sig ? (*p == *str) : (toupper(*p)==toupper(*str))))
1293 str++;
1294 str--; /* We've eaten the match char after the '*' */
1295 if(do_match(str,p,case_sig)) {
1296 return True;
1298 if(!*str) {
1299 return False;
1300 } else {
1301 str++;
1304 return False;
1306 default:
1307 if(case_sig) {
1308 if(*str != *p) {
1309 return False;
1311 } else {
1312 if(toupper(*str) != toupper(*p)) {
1313 return False;
1316 str++, p++;
1317 break;
1321 if(!*p && !*str)
1322 return True;
1324 if (!*p && str[0] == '.' && str[1] == 0) {
1325 return(True);
1328 if (!*str && *p == '?') {
1329 while (*p == '?')
1330 p++;
1331 return(!*p);
1334 if(!*str && (*p == '*' && p[1] == '\0')) {
1335 return True;
1338 return False;
1342 /*********************************************************
1343 * Routine to match a given string with a regexp - uses
1344 * simplified regexp that takes * and ? only. Case can be
1345 * significant or not.
1346 * The 8.3 handling was rewritten by Ums Harald <Harald.Ums@pro-sieben.de>
1347 * This is the new 'NT style' matcher.
1348 *********************************************************/
1350 BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
1352 char *p;
1353 pstring t_pattern, t_filename, te_pattern, te_filename;
1354 fstring ebase,eext,sbase,sext;
1356 BOOL matched = False;
1358 /* Make local copies of str and regexp */
1359 pstrcpy(t_pattern,regexp);
1360 pstrcpy(t_filename,str);
1362 if(trans2) {
1364 /* a special case for 16 bit apps */
1365 if (strequal(t_pattern,"????????.???"))
1366 pstrcpy(t_pattern,"*");
1368 #if 0
1370 * Handle broken clients that send us old 8.3 format.
1372 string_sub(t_pattern,"????????","*");
1373 string_sub(t_pattern,".???",".*");
1374 #endif
1377 #if 0
1379 * Not sure if this is a good idea. JRA.
1381 if(trans2 && is_8_3(t_pattern,False) && is_8_3(t_filename,False))
1382 trans2 = False;
1383 #endif
1385 #if 0
1386 if (!strchr(t_filename,'.')) {
1387 pstrcat(t_filename,".");
1389 #endif
1391 /* Remove any *? and ** as they are meaningless */
1392 string_sub(t_pattern, "*?", "*");
1393 string_sub(t_pattern, "**", "*");
1395 if (strequal(t_pattern,"*"))
1396 return(True);
1398 DEBUG(8,("mask_match str=<%s> regexp=<%s>, case_sig = %d\n", t_filename, t_pattern, case_sig));
1400 if(trans2) {
1402 * Match each component of the regexp, split up by '.'
1403 * characters.
1405 char *fp, *rp, *cp2, *cp1;
1406 BOOL last_wcard_was_star = False;
1407 int num_path_components, num_regexp_components;
1409 pstrcpy(te_pattern,t_pattern);
1410 pstrcpy(te_filename,t_filename);
1412 * Remove multiple "*." patterns.
1414 string_sub(te_pattern, "*.*.", "*.");
1415 num_regexp_components = count_chars(te_pattern, '.');
1416 num_path_components = count_chars(te_filename, '.');
1419 * Check for special 'hack' case of "DIR a*z". - needs to match a.b.c...z
1421 if(num_regexp_components == 0)
1422 matched = do_match( te_filename, te_pattern, case_sig);
1423 else {
1424 for( cp1 = te_pattern, cp2 = te_filename; cp1;) {
1425 fp = strchr(cp2, '.');
1426 if(fp)
1427 *fp = '\0';
1428 rp = strchr(cp1, '.');
1429 if(rp)
1430 *rp = '\0';
1432 if(cp1[strlen(cp1)-1] == '*')
1433 last_wcard_was_star = True;
1434 else
1435 last_wcard_was_star = False;
1437 if(!do_match(cp2, cp1, case_sig))
1438 break;
1440 cp1 = rp ? rp + 1 : NULL;
1441 cp2 = fp ? fp + 1 : "";
1443 if(last_wcard_was_star || ((cp1 != NULL) && (*cp1 == '*'))) {
1444 /* Eat the extra path components. */
1445 int i;
1447 for(i = 0; i < num_path_components - num_regexp_components; i++) {
1448 fp = strchr(cp2, '.');
1449 if(fp)
1450 *fp = '\0';
1452 if((cp1 != NULL) && do_match( cp2, cp1, case_sig)) {
1453 cp2 = fp ? fp + 1 : "";
1454 break;
1456 cp2 = fp ? fp + 1 : "";
1458 num_path_components -= i;
1461 if(cp1 == NULL && ((*cp2 == '\0') || last_wcard_was_star))
1462 matched = True;
1464 } else {
1466 /* -------------------------------------------------
1467 * Behaviour of Win95
1468 * for 8.3 filenames and 8.3 Wildcards
1469 * -------------------------------------------------
1471 if (strequal (t_filename, ".")) {
1473 * Patterns: *.* *. ?. ? ????????.??? are valid.
1476 if(strequal(t_pattern, "*.*") || strequal(t_pattern, "*.") ||
1477 strequal(t_pattern, "????????.???") ||
1478 strequal(t_pattern, "?.") || strequal(t_pattern, "?"))
1479 matched = True;
1480 } else if (strequal (t_filename, "..")) {
1482 * Patterns: *.* *. ?. ? *.? ????????.??? are valid.
1485 if(strequal(t_pattern, "*.*") || strequal(t_pattern, "*.") ||
1486 strequal(t_pattern, "?.") || strequal(t_pattern, "?") ||
1487 strequal(t_pattern, "????????.???") ||
1488 strequal(t_pattern, "*.?") || strequal(t_pattern, "?.*"))
1489 matched = True;
1490 } else {
1492 if ((p = strrchr (t_pattern, '.'))) {
1494 * Wildcard has a suffix.
1496 *p = 0;
1497 fstrcpy (ebase, t_pattern);
1498 if (p[1]) {
1499 fstrcpy (eext, p + 1);
1500 } else {
1501 /* pattern ends in DOT: treat as if there is no DOT */
1502 *eext = 0;
1503 if (strequal (ebase, "*"))
1504 return (True);
1506 } else {
1508 * No suffix for wildcard.
1510 fstrcpy (ebase, t_pattern);
1511 eext[0] = 0;
1514 p = strrchr (t_filename, '.');
1515 if (p && (p[1] == 0) ) {
1517 * Filename has an extension of '.' only.
1519 *p = 0; /* nuke dot at end of string */
1520 p = 0; /* and treat it as if there is no extension */
1523 if (p) {
1525 * Filename has an extension.
1527 *p = 0;
1528 fstrcpy (sbase, t_filename);
1529 fstrcpy (sext, p + 1);
1530 if (*eext) {
1531 matched = do_match(sbase, ebase, case_sig)
1532 && do_match(sext, eext, case_sig);
1533 } else {
1534 /* pattern has no extension */
1535 /* Really: match complete filename with pattern ??? means exactly 3 chars */
1536 matched = do_match(str, ebase, case_sig);
1538 } else {
1540 * Filename has no extension.
1542 fstrcpy (sbase, t_filename);
1543 fstrcpy (sext, "");
1544 if (*eext) {
1545 /* pattern has extension */
1546 matched = do_match(sbase, ebase, case_sig)
1547 && do_match(sext, eext, case_sig);
1548 } else {
1549 matched = do_match(sbase, ebase, case_sig);
1550 #ifdef EMULATE_WEIRD_W95_MATCHING
1552 * Even Microsoft has some problems
1553 * Behaviour Win95 -> local disk
1554 * is different from Win95 -> smb drive from Nt 4.0
1555 * This branch would reflect the Win95 local disk behaviour
1557 if (!matched) {
1558 /* a? matches aa and a in w95 */
1559 fstrcat (sbase, ".");
1560 matched = do_match(sbase, ebase, case_sig);
1562 #endif
1568 DEBUG(8,("mask_match returning %d\n", matched));
1570 return matched;
1572 #endif /* 0 */
1574 #if 0
1575 /****************************************************************************
1576 set the length of a file from a filedescriptor.
1577 Returns 0 on success, -1 on failure.
1578 ****************************************************************************/
1580 int set_filelen(int fd, SMB_OFF_T len)
1582 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1583 extend a file with ftruncate. Provide alternate implementation
1584 for this */
1586 #ifdef HAVE_FTRUNCATE_EXTEND
1587 return sys_ftruncate(fd, len);
1588 #else
1589 SMB_STRUCT_STAT st;
1590 char c = 0;
1591 SMB_OFF_T currpos = sys_lseek(fd, (SMB_OFF_T)0, SEEK_CUR);
1593 if(currpos == -1)
1594 return -1;
1595 /* Do an fstat to see if the file is longer than
1596 the requested size (call ftruncate),
1597 or shorter, in which case seek to len - 1 and write 1
1598 byte of zero */
1599 if(sys_fstat(fd, &st)<0)
1600 return -1;
1602 #ifdef S_ISFIFO
1603 if (S_ISFIFO(st.st_mode))
1604 return 0;
1605 #endif
1607 if(st.st_size == len)
1608 return 0;
1609 if(st.st_size > len)
1610 return sys_ftruncate(fd, len);
1612 if(sys_lseek(fd, len-1, SEEK_SET) != len -1)
1613 return -1;
1614 if(write(fd, &c, 1)!=1)
1615 return -1;
1616 /* Seek to where we were */
1617 if(sys_lseek(fd, currpos, SEEK_SET) != currpos)
1618 return -1;
1619 return 0;
1620 #endif
1624 #ifdef HPUX
1625 /****************************************************************************
1626 this is a version of setbuffer() for those machines that only have setvbuf
1627 ****************************************************************************/
1628 void setbuffer(FILE *f,char *buf,int bufsize)
1630 setvbuf(f,buf,_IOFBF,bufsize);
1632 #endif
1633 #endif /* 0 */
1637 /****************************************************************************
1638 expand a pointer to be a particular size
1639 ****************************************************************************/
1640 void *Realloc(void *p,size_t size)
1642 void *ret=NULL;
1644 if (size == 0) {
1645 if (p) free(p);
1646 DEBUG(5,("Realloc asked for 0 bytes\n"));
1647 return NULL;
1650 if (!p)
1651 ret = (void *)malloc(size);
1652 else
1653 ret = (void *)realloc(p,size);
1655 #ifdef MEM_MAN
1657 extern FILE *dbf;
1658 smb_mem_write_info(ret, dbf);
1660 #endif
1662 if (!ret)
1663 DEBUG(0,("Memory allocation error: failed to expand to %d bytes\n",(int)size));
1665 return(ret);
1669 /****************************************************************************
1670 get my own name and IP
1671 ****************************************************************************/
1672 BOOL get_myname(char *my_name,struct in_addr *ip)
1674 struct hostent *hp;
1675 pstring hostname;
1677 *hostname = 0;
1679 /* get my host name */
1680 if (gethostname(hostname, sizeof(hostname)) == -1)
1682 DEBUG(0,("gethostname failed\n"));
1683 return False;
1686 /* Ensure null termination. */
1687 hostname[sizeof(hostname)-1] = '\0';
1689 /* get host info */
1690 if ((hp = Get_Hostbyname(hostname)) == 0)
1692 DEBUG(0,( "Get_Hostbyname: Unknown host %s\n",hostname));
1693 return False;
1696 if (my_name)
1698 /* split off any parts after an initial . */
1699 char *p = strchr(hostname,'.');
1700 if (p) *p = 0;
1702 fstrcpy(my_name,hostname);
1705 if (ip)
1706 putip((char *)ip,(char *)hp->h_addr);
1708 return(True);
1712 /****************************************************************************
1713 true if two IP addresses are equal
1714 ****************************************************************************/
1715 BOOL ip_equal(struct in_addr ip1,struct in_addr ip2)
1717 uint32 a1,a2;
1718 a1 = ntohl(ip1.s_addr);
1719 a2 = ntohl(ip2.s_addr);
1720 return(a1 == a2);
1723 #if 0 /* May be useful one day */
1724 /****************************************************************************
1725 interpret a protocol description string, with a default
1726 ****************************************************************************/
1727 int interpret_protocol(char *str,int def)
1729 if (strequal(str,"NT1"))
1730 return(PROTOCOL_NT1);
1731 if (strequal(str,"LANMAN2"))
1732 return(PROTOCOL_LANMAN2);
1733 if (strequal(str,"LANMAN1"))
1734 return(PROTOCOL_LANMAN1);
1735 if (strequal(str,"CORE"))
1736 return(PROTOCOL_CORE);
1737 if (strequal(str,"COREPLUS"))
1738 return(PROTOCOL_COREPLUS);
1739 if (strequal(str,"CORE+"))
1740 return(PROTOCOL_COREPLUS);
1742 DEBUG(0,("Unrecognised protocol level %s\n",str));
1744 return(def);
1746 #endif /* 0 */
1748 /****************************************************************************
1749 interpret an internet address or name into an IP address in 4 byte form
1750 ****************************************************************************/
1751 uint32 interpret_addr(char *str)
1753 struct hostent *hp;
1754 uint32 res;
1755 int i;
1756 BOOL pure_address = True;
1758 if (strcmp(str,"0.0.0.0") == 0) return(0);
1759 if (strcmp(str,"255.255.255.255") == 0) return(0xFFFFFFFF);
1761 for (i=0; pure_address && str[i]; i++)
1762 if (!(isdigit((int)str[i]) || str[i] == '.'))
1763 pure_address = False;
1765 /* if it's in the form of an IP address then get the lib to interpret it */
1766 if (pure_address) {
1767 res = inet_addr(str);
1768 } else {
1769 /* otherwise assume it's a network name of some sort and use
1770 Get_Hostbyname */
1771 if ((hp = Get_Hostbyname(str)) == 0) {
1772 DEBUG(3,("Get_Hostbyname: Unknown host. %s\n",str));
1773 return 0;
1775 if(hp->h_addr == NULL) {
1776 DEBUG(3,("Get_Hostbyname: host address is invalid for host %s\n",str));
1777 return 0;
1779 putip((char *)&res,(char *)hp->h_addr);
1782 if (res == (uint32)-1) return(0);
1784 return(res);
1787 /*******************************************************************
1788 a convenient addition to interpret_addr()
1789 ******************************************************************/
1790 struct in_addr *interpret_addr2(char *str)
1792 static struct in_addr ret;
1793 uint32 a = interpret_addr(str);
1794 ret.s_addr = a;
1795 return(&ret);
1798 /*******************************************************************
1799 check if an IP is the 0.0.0.0
1800 ******************************************************************/
1801 BOOL zero_ip(struct in_addr ip)
1803 uint32 a;
1804 putip((char *)&a,(char *)&ip);
1805 return(a == 0);
1809 /*******************************************************************
1810 matchname - determine if host name matches IP address
1811 ******************************************************************/
1812 BOOL matchname(char *remotehost,struct in_addr addr)
1814 struct hostent *hp;
1815 int i;
1817 if ((hp = Get_Hostbyname(remotehost)) == 0) {
1818 DEBUG(0,("Get_Hostbyname(%s): lookup failure.\n", remotehost));
1819 return False;
1823 * Make sure that gethostbyname() returns the "correct" host name.
1824 * Unfortunately, gethostbyname("localhost") sometimes yields
1825 * "localhost.domain". Since the latter host name comes from the
1826 * local DNS, we just have to trust it (all bets are off if the local
1827 * DNS is perverted). We always check the address list, though.
1830 if (strcasecmp(remotehost, hp->h_name)
1831 && strcasecmp(remotehost, "localhost")) {
1832 DEBUG(0,("host name/name mismatch: %s != %s\n",
1833 remotehost, hp->h_name));
1834 return False;
1837 /* Look up the host address in the address list we just got. */
1838 for (i = 0; hp->h_addr_list[i]; i++) {
1839 if (memcmp(hp->h_addr_list[i], (caddr_t) & addr, sizeof(addr)) == 0)
1840 return True;
1844 * The host name does not map to the original host address. Perhaps
1845 * someone has compromised a name server. More likely someone botched
1846 * it, but that could be dangerous, too.
1849 DEBUG(0,("host name/address mismatch: %s != %s\n",
1850 inet_ntoa(addr), hp->h_name));
1851 return False;
1855 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
1856 /******************************************************************
1857 Remove any mount options such as -rsize=2048,wsize=2048 etc.
1858 Based on a fix from <Thomas.Hepper@icem.de>.
1859 *******************************************************************/
1861 static void strip_mount_options( pstring *str)
1863 if (**str == '-')
1865 char *p = *str;
1866 while(*p && !isspace(*p))
1867 p++;
1868 while(*p && isspace(*p))
1869 p++;
1870 if(*p) {
1871 pstring tmp_str;
1873 pstrcpy(tmp_str, p);
1874 pstrcpy(*str, tmp_str);
1879 /*******************************************************************
1880 Patch from jkf@soton.ac.uk
1881 Split Luke's automount_server into YP lookup and string splitter
1882 so can easily implement automount_path().
1883 As we may end up doing both, cache the last YP result.
1884 *******************************************************************/
1886 #ifdef WITH_NISPLUS_HOME
1887 static char *automount_lookup(char *user_name)
1889 static fstring last_key = "";
1890 static pstring last_value = "";
1892 char *nis_map = (char *)lp_nis_home_map_name();
1894 char buffer[NIS_MAXATTRVAL + 1];
1895 nis_result *result;
1896 nis_object *object;
1897 entry_obj *entry;
1899 DEBUG(5, ("NIS+ Domain: %s\n", (char *)nis_local_directory()));
1901 if (strcmp(user_name, last_key))
1903 slprintf(buffer, sizeof(buffer)-1, "[%s=%s]%s.%s", "key", user_name, nis_map,
1904 (char *)nis_local_directory());
1905 DEBUG(5, ("NIS+ querystring: %s\n", buffer));
1907 if (result = nis_list(buffer, RETURN_RESULT, NULL, NULL))
1909 if (result->status != NIS_SUCCESS)
1911 DEBUG(3, ("NIS+ query failed: %s\n", nis_sperrno(result->status)));
1912 fstrcpy(last_key, ""); pstrcpy(last_value, "");
1914 else
1916 object = result->objects.objects_val;
1917 if (object->zo_data.zo_type == ENTRY_OBJ)
1919 entry = &object->zo_data.objdata_u.en_data;
1920 DEBUG(5, ("NIS+ entry type: %s\n", entry->en_type));
1921 DEBUG(3, ("NIS+ result: %s\n", entry->en_cols.en_cols_val[1].ec_value.ec_value_val));
1923 pstrcpy(last_value, entry->en_cols.en_cols_val[1].ec_value.ec_value_val);
1924 string_sub(last_value, "&", user_name);
1925 fstrcpy(last_key, user_name);
1929 nis_freeresult(result);
1932 strip_mount_options(&last_value);
1934 DEBUG(4, ("NIS+ Lookup: %s resulted in %s\n", user_name, last_value));
1935 return last_value;
1937 #else /* WITH_NISPLUS_HOME */
1938 static char *automount_lookup(char *user_name)
1940 static fstring last_key = "";
1941 static pstring last_value = "";
1943 int nis_error; /* returned by yp all functions */
1944 char *nis_result; /* yp_match inits this */
1945 int nis_result_len; /* and set this */
1946 char *nis_domain; /* yp_get_default_domain inits this */
1947 char *nis_map = (char *)lp_nis_home_map_name();
1949 if ((nis_error = yp_get_default_domain(&nis_domain)) != 0)
1951 DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
1952 return last_value;
1955 DEBUG(5, ("NIS Domain: %s\n", nis_domain));
1957 if (!strcmp(user_name, last_key))
1959 nis_result = last_value;
1960 nis_result_len = strlen(last_value);
1961 nis_error = 0;
1963 else
1965 if ((nis_error = yp_match(nis_domain, nis_map,
1966 user_name, strlen(user_name),
1967 &nis_result, &nis_result_len)) != 0)
1969 DEBUG(3, ("YP Error: \"%s\" while looking up \"%s\" in map \"%s\"\n",
1970 yperr_string(nis_error), user_name, nis_map));
1972 if (!nis_error && nis_result_len >= sizeof(pstring))
1974 nis_result_len = sizeof(pstring)-1;
1976 fstrcpy(last_key, user_name);
1977 strncpy(last_value, nis_result, nis_result_len);
1978 last_value[nis_result_len] = '\0';
1981 strip_mount_options(&last_value);
1983 DEBUG(4, ("YP Lookup: %s resulted in %s\n", user_name, last_value));
1984 return last_value;
1986 #endif /* WITH_NISPLUS_HOME */
1987 #endif
1989 /*******************************************************************
1990 Patch from jkf@soton.ac.uk
1991 This is Luke's original function with the NIS lookup code
1992 moved out to a separate function.
1993 *******************************************************************/
1994 static char *automount_server(char *user_name)
1996 static pstring server_name;
1998 /* use the local machine name as the default */
1999 /* this will be the default if WITH_AUTOMOUNT is not used or fails */
2000 pstrcpy(server_name, local_machine);
2002 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
2004 if (lp_nis_home_map())
2006 int home_server_len;
2007 char *automount_value = automount_lookup(user_name);
2008 home_server_len = strcspn(automount_value,":");
2009 DEBUG(5, ("NIS lookup succeeded. Home server length: %d\n",home_server_len));
2010 if (home_server_len > sizeof(pstring))
2012 home_server_len = sizeof(pstring);
2014 strncpy(server_name, automount_value, home_server_len);
2015 server_name[home_server_len] = '\0';
2017 #endif
2019 DEBUG(4,("Home server: %s\n", server_name));
2021 return server_name;
2024 /*******************************************************************
2025 Patch from jkf@soton.ac.uk
2026 Added this to implement %p (NIS auto-map version of %H)
2027 *******************************************************************/
2028 static char *automount_path(char *user_name)
2030 static pstring server_path;
2032 /* use the passwd entry as the default */
2033 /* this will be the default if WITH_AUTOMOUNT is not used or fails */
2034 /* pstrcpy() copes with get_home_dir() returning NULL */
2035 pstrcpy(server_path, get_home_dir(user_name));
2037 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
2039 if (lp_nis_home_map())
2041 char *home_path_start;
2042 char *automount_value = automount_lookup(user_name);
2043 home_path_start = strchr(automount_value,':');
2044 if (home_path_start != NULL)
2046 DEBUG(5, ("NIS lookup succeeded. Home path is: %s\n",
2047 home_path_start?(home_path_start+1):""));
2048 pstrcpy(server_path, home_path_start+1);
2051 #endif
2053 DEBUG(4,("Home server path: %s\n", server_path));
2055 return server_path;
2059 /*******************************************************************
2060 sub strings with useful parameters
2061 Rewritten by Stefaan A Eeckels <Stefaan.Eeckels@ecc.lu> and
2062 Paul Rippin <pr3245@nopc.eurostat.cec.be>
2063 ********************************************************************/
2064 void standard_sub_basic(char *str)
2066 char *s, *p;
2067 char pidstr[10];
2068 struct passwd *pass;
2069 char *username = sam_logon_in_ssb ? samlogon_user : sesssetup_user;
2071 for (s = str ; s && *s && (p = strchr(s,'%')); s = p )
2073 switch (*(p+1))
2075 case 'G' :
2077 if ((pass = Get_Pwnam(username,False))!=NULL)
2079 string_sub(p,"%G",gidtoname(pass->pw_gid));
2081 else
2083 p += 2;
2085 break;
2087 case 'N' : string_sub(p,"%N", automount_server(username)); break;
2088 case 'I' : string_sub(p,"%I", client_addr(Client)); break;
2089 case 'L' : string_sub(p,"%L", local_machine); break;
2090 case 'M' : string_sub(p,"%M", client_name(Client)); break;
2091 case 'R' : string_sub(p,"%R", remote_proto); break;
2092 case 'T' : string_sub(p,"%T", timestring()); break;
2093 case 'U' : string_sub(p,"%U", username); break;
2094 case 'a' : string_sub(p,"%a", remote_arch); break;
2095 case 'd' :
2097 slprintf(pidstr,sizeof(pidstr) - 1, "%d",(int)getpid());
2098 string_sub(p,"%d", pidstr);
2099 break;
2101 case 'h' : string_sub(p,"%h", myhostname); break;
2102 case 'm' : string_sub(p,"%m", remote_machine); break;
2103 case 'v' : string_sub(p,"%v", VERSION); break;
2104 case '$' : /* Expand environment variables */
2106 /* Contributed by Branko Cibej <branko.cibej@hermes.si> */
2107 fstring envname;
2108 char *envval;
2109 char *q, *r;
2110 int copylen;
2112 if (*(p+2) != '(')
2114 p+=2;
2115 break;
2117 if ((q = strchr(p,')')) == NULL)
2119 DEBUG(0,("standard_sub_basic: Unterminated environment \
2120 variable [%s]\n", p));
2121 p+=2;
2122 break;
2125 r = p+3;
2126 copylen = MIN((q-r),(sizeof(envname)-1));
2127 strncpy(envname,r,copylen);
2128 envname[copylen] = '\0';
2130 if ((envval = getenv(envname)) == NULL)
2132 DEBUG(0,("standard_sub_basic: Environment variable [%s] not set\n",
2133 envname));
2134 p+=2;
2135 break;
2138 copylen = MIN((q+1-p),(sizeof(envname)-1));
2139 strncpy(envname,p,copylen);
2140 envname[copylen] = '\0';
2141 string_sub(p,envname,envval);
2142 break;
2144 case '\0': p++; break; /* don't run off end if last character is % */
2145 default : p+=2; break;
2148 return;
2152 /****************************************************************************
2153 do some standard substitutions in a string
2154 ****************************************************************************/
2155 void standard_sub(connection_struct *conn,char *str)
2157 char *p, *s, *home;
2159 for (s=str; (p=strchr(s, '%'));s=p) {
2160 switch (*(p+1)) {
2161 case 'H':
2162 if ((home = get_home_dir(conn->user))) {
2163 string_sub(p,"%H",home);
2164 } else {
2165 p += 2;
2167 break;
2169 case 'P':
2170 string_sub(p,"%P",conn->connectpath);
2171 break;
2173 case 'S':
2174 string_sub(p,"%S",
2175 lp_servicename(SNUM(conn)));
2176 break;
2178 case 'g':
2179 string_sub(p,"%g",
2180 gidtoname(conn->gid));
2181 break;
2182 case 'u':
2183 string_sub(p,"%u",conn->user);
2184 break;
2186 /* Patch from jkf@soton.ac.uk Left the %N (NIS
2187 * server name) in standard_sub_basic as it is
2188 * a feature for logon servers, hence uses the
2189 * username. The %p (NIS server path) code is
2190 * here as it is used instead of the default
2191 * "path =" string in [homes] and so needs the
2192 * service name, not the username. */
2193 case 'p':
2194 string_sub(p,"%p",
2195 automount_path(lp_servicename(SNUM(conn))));
2196 break;
2197 case '\0':
2198 p++;
2199 break; /* don't run off the end of the string
2202 default: p+=2;
2203 break;
2207 standard_sub_basic(str);
2212 /*******************************************************************
2213 are two IPs on the same subnet?
2214 ********************************************************************/
2215 BOOL same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask)
2217 uint32 net1,net2,nmask;
2219 nmask = ntohl(mask.s_addr);
2220 net1 = ntohl(ip1.s_addr);
2221 net2 = ntohl(ip2.s_addr);
2223 return((net1 & nmask) == (net2 & nmask));
2227 /****************************************************************************
2228 a wrapper for gethostbyname() that tries with all lower and all upper case
2229 if the initial name fails
2230 ****************************************************************************/
2231 struct hostent *Get_Hostbyname(const char *name)
2233 char *name2 = strdup(name);
2234 struct hostent *ret;
2236 if (!name2)
2238 DEBUG(0,("Memory allocation error in Get_Hostbyname! panic\n"));
2239 exit(0);
2244 * This next test is redundent and causes some systems (with
2245 * broken isalnum() calls) problems.
2246 * JRA.
2249 #if 0
2250 if (!isalnum(*name2))
2252 free(name2);
2253 return(NULL);
2255 #endif /* 0 */
2257 ret = sys_gethostbyname(name2);
2258 if (ret != NULL)
2260 free(name2);
2261 return(ret);
2264 /* try with all lowercase */
2265 strlower(name2);
2266 ret = sys_gethostbyname(name2);
2267 if (ret != NULL)
2269 free(name2);
2270 return(ret);
2273 /* try with all uppercase */
2274 strupper(name2);
2275 ret = sys_gethostbyname(name2);
2276 if (ret != NULL)
2278 free(name2);
2279 return(ret);
2282 /* nothing works :-( */
2283 free(name2);
2284 return(NULL);
2288 /*******************************************************************
2289 turn a uid into a user name
2290 ********************************************************************/
2291 char *uidtoname(uid_t uid)
2293 static char name[40];
2294 struct passwd *pass = getpwuid(uid);
2295 if (pass) return(pass->pw_name);
2296 slprintf(name, sizeof(name) - 1, "%d",(int)uid);
2297 return(name);
2301 /*******************************************************************
2302 turn a gid into a group name
2303 ********************************************************************/
2305 char *gidtoname(gid_t gid)
2307 static char name[40];
2308 struct group *grp = getgrgid(gid);
2309 if (grp) return(grp->gr_name);
2310 slprintf(name,sizeof(name) - 1, "%d",(int)gid);
2311 return(name);
2314 /*******************************************************************
2315 turn a user name into a uid
2316 ********************************************************************/
2317 uid_t nametouid(const char *name)
2319 struct passwd *pass = getpwnam(name);
2320 if (pass) return(pass->pw_uid);
2321 return (uid_t)-1;
2324 /*******************************************************************
2325 something really nasty happened - panic!
2326 ********************************************************************/
2327 void smb_panic(char *why)
2329 char *cmd = lp_panic_action();
2330 if (cmd && *cmd) {
2331 system(cmd);
2333 DEBUG(0,("PANIC: %s\n", why));
2334 dbgflush();
2335 abort();
2338 #if 0
2339 /*******************************************************************
2340 a readdir wrapper which just returns the file name
2341 ********************************************************************/
2342 char *readdirname(DIR *p)
2344 SMB_STRUCT_DIRENT *ptr;
2345 char *dname;
2347 if (!p) return(NULL);
2349 ptr = (SMB_STRUCT_DIRENT *)sys_readdir(p);
2350 if (!ptr) return(NULL);
2352 dname = ptr->d_name;
2354 #ifdef NEXT2
2355 if (telldir(p) < 0) return(NULL);
2356 #endif
2358 #ifdef HAVE_BROKEN_READDIR
2359 /* using /usr/ucb/cc is BAD */
2360 dname = dname - 2;
2361 #endif
2364 static pstring buf;
2365 memcpy(buf, dname, NAMLEN(ptr)+1);
2366 dname = buf;
2369 return(dname);
2372 /*******************************************************************
2373 Utility function used to decide if the last component
2374 of a path matches a (possibly wildcarded) entry in a namelist.
2375 ********************************************************************/
2377 BOOL is_in_path(char *name, name_compare_entry *namelist)
2379 pstring last_component;
2380 char *p;
2382 DEBUG(8, ("is_in_path: %s\n", name));
2384 /* if we have no list it's obviously not in the path */
2385 if((namelist == NULL ) || ((namelist != NULL) && (namelist[0].name == NULL)))
2387 DEBUG(8,("is_in_path: no name list.\n"));
2388 return False;
2391 /* Get the last component of the unix name. */
2392 p = strrchr(name, '/');
2393 strncpy(last_component, p ? ++p : name, sizeof(last_component)-1);
2394 last_component[sizeof(last_component)-1] = '\0';
2396 for(; namelist->name != NULL; namelist++)
2398 if(namelist->is_wild)
2401 * Look for a wildcard match. Use the old
2402 * 'unix style' mask match, rather than the
2403 * new NT one.
2405 if (unix_mask_match(last_component, namelist->name, case_sensitive, False))
2407 DEBUG(8,("is_in_path: mask match succeeded\n"));
2408 return True;
2411 else
2413 if((case_sensitive && (strcmp(last_component, namelist->name) == 0))||
2414 (!case_sensitive && (StrCaseCmp(last_component, namelist->name) == 0)))
2416 DEBUG(8,("is_in_path: match succeeded\n"));
2417 return True;
2421 DEBUG(8,("is_in_path: match not found\n"));
2423 return False;
2426 /*******************************************************************
2427 Strip a '/' separated list into an array of
2428 name_compare_enties structures suitable for
2429 passing to is_in_path(). We do this for
2430 speed so we can pre-parse all the names in the list
2431 and don't do it for each call to is_in_path().
2432 namelist is modified here and is assumed to be
2433 a copy owned by the caller.
2434 We also check if the entry contains a wildcard to
2435 remove a potentially expensive call to mask_match
2436 if possible.
2437 ********************************************************************/
2439 void set_namearray(name_compare_entry **ppname_array, char *namelist)
2441 char *name_end;
2442 char *nameptr = namelist;
2443 int num_entries = 0;
2444 int i;
2446 (*ppname_array) = NULL;
2448 if((nameptr == NULL ) || ((nameptr != NULL) && (*nameptr == '\0')))
2449 return;
2451 /* We need to make two passes over the string. The
2452 first to count the number of elements, the second
2453 to split it.
2455 while(*nameptr)
2457 if ( *nameptr == '/' )
2459 /* cope with multiple (useless) /s) */
2460 nameptr++;
2461 continue;
2463 /* find the next / */
2464 name_end = strchr(nameptr, '/');
2466 /* oops - the last check for a / didn't find one. */
2467 if (name_end == NULL)
2468 break;
2470 /* next segment please */
2471 nameptr = name_end + 1;
2472 num_entries++;
2475 if(num_entries == 0)
2476 return;
2478 if(( (*ppname_array) = (name_compare_entry *)malloc(
2479 (num_entries + 1) * sizeof(name_compare_entry))) == NULL)
2481 DEBUG(0,("set_namearray: malloc fail\n"));
2482 return;
2485 /* Now copy out the names */
2486 nameptr = namelist;
2487 i = 0;
2488 while(*nameptr)
2490 if ( *nameptr == '/' )
2492 /* cope with multiple (useless) /s) */
2493 nameptr++;
2494 continue;
2496 /* find the next / */
2497 if ((name_end = strchr(nameptr, '/')) != NULL)
2499 *name_end = 0;
2502 /* oops - the last check for a / didn't find one. */
2503 if(name_end == NULL)
2504 break;
2506 (*ppname_array)[i].is_wild = ((strchr( nameptr, '?')!=NULL) ||
2507 (strchr( nameptr, '*')!=NULL));
2508 if(((*ppname_array)[i].name = strdup(nameptr)) == NULL)
2510 DEBUG(0,("set_namearray: malloc fail (1)\n"));
2511 return;
2514 /* next segment please */
2515 nameptr = name_end + 1;
2516 i++;
2519 (*ppname_array)[i].name = NULL;
2521 return;
2524 /****************************************************************************
2525 routine to free a namearray.
2526 ****************************************************************************/
2528 void free_namearray(name_compare_entry *name_array)
2530 if(name_array == 0)
2531 return;
2533 if(name_array->name != NULL)
2534 free(name_array->name);
2536 free((char *)name_array);
2539 /****************************************************************************
2540 routine to do file locking
2541 ****************************************************************************/
2542 BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
2544 #ifdef HAVE_FCNTL_LOCK
2545 SMB_STRUCT_FLOCK lock;
2546 int ret;
2548 if(lp_ole_locking_compat()) {
2549 SMB_OFF_T mask2= ((SMB_OFF_T)0x3) << (SMB_OFF_T_BITS-4);
2550 SMB_OFF_T mask = (mask2<<2);
2552 /* make sure the count is reasonable, we might kill the lockd otherwise */
2553 count &= ~mask;
2555 /* the offset is often strange - remove 2 of its bits if either of
2556 the top two bits are set. Shift the top ones by two bits. This
2557 still allows OLE2 apps to operate, but should stop lockd from
2558 dieing */
2559 if ((offset & mask) != 0)
2560 offset = (offset & ~mask) | (((offset & mask) >> 2) & mask2);
2561 } else {
2562 SMB_OFF_T mask2 = ((SMB_OFF_T)0x4) << (SMB_OFF_T_BITS-4);
2563 SMB_OFF_T mask = (mask2<<1);
2564 SMB_OFF_T neg_mask = ~mask;
2566 /* interpret negative counts as large numbers */
2567 if (count < 0)
2568 count &= ~mask;
2570 /* no negative offsets */
2571 if(offset < 0)
2572 offset &= ~mask;
2574 /* count + offset must be in range */
2575 while ((offset < 0 || (offset + count < 0)) && mask)
2577 offset &= ~mask;
2578 mask = ((mask >> 1) & neg_mask);
2582 DEBUG(8,("fcntl_lock %d %d %.0f %.0f %d\n",fd,op,(double)offset,(double)count,type));
2584 lock.l_type = type;
2585 lock.l_whence = SEEK_SET;
2586 lock.l_start = offset;
2587 lock.l_len = count;
2588 lock.l_pid = 0;
2590 errno = 0;
2592 ret = fcntl(fd,op,&lock);
2593 if (errno == EFBIG)
2595 if( DEBUGLVL( 0 ))
2597 dbgtext("fcntl_lock: WARNING: lock request at offset %.0f, length %.0f returned\n", (double)offset,(double)count);
2598 dbgtext("a 'file too large' error. This can happen when using 64 bit lock offsets\n");
2599 dbgtext("on 32 bit NFS mounted file systems. Retrying with 32 bit truncated length.\n");
2601 /* 32 bit NFS file system, retry with smaller offset */
2602 errno = 0;
2603 lock.l_len = count & 0xffffffff;
2604 ret = fcntl(fd,op,&lock);
2607 if (errno != 0)
2608 DEBUG(3,("fcntl lock gave errno %d (%s)\n",errno,strerror(errno)));
2610 /* a lock query */
2611 if (op == SMB_F_GETLK)
2613 if ((ret != -1) &&
2614 (lock.l_type != F_UNLCK) &&
2615 (lock.l_pid != 0) &&
2616 (lock.l_pid != getpid()))
2618 DEBUG(3,("fd %d is locked by pid %d\n",fd,(int)lock.l_pid));
2619 return(True);
2622 /* it must be not locked or locked by me */
2623 return(False);
2626 /* a lock set or unset */
2627 if (ret == -1)
2629 DEBUG(3,("lock failed at offset %.0f count %.0f op %d type %d (%s)\n",
2630 (double)offset,(double)count,op,type,strerror(errno)));
2632 /* perhaps it doesn't support this sort of locking?? */
2633 if (errno == EINVAL)
2635 DEBUG(3,("locking not supported? returning True\n"));
2636 return(True);
2639 return(False);
2642 /* everything went OK */
2643 DEBUG(8,("Lock call successful\n"));
2645 return(True);
2646 #else
2647 return(False);
2648 #endif
2651 /*******************************************************************
2652 is the name specified one of my netbios names
2653 returns true is it is equal, false otherwise
2654 ********************************************************************/
2655 BOOL is_myname(char *s)
2657 int n;
2658 BOOL ret = False;
2660 for (n=0; my_netbios_names[n]; n++) {
2661 if (strequal(my_netbios_names[n], s))
2662 ret=True;
2664 DEBUG(8, ("is_myname(\"%s\") returns %d\n", s, ret));
2665 return(ret);
2667 #endif /* 0 */
2668 #if 0 /* Can be useful one day */
2669 /*******************************************************************
2670 set the horrid remote_arch string based on an enum.
2671 ********************************************************************/
2672 void set_remote_arch(enum remote_arch_types type)
2674 ra_type = type;
2675 switch( type )
2677 case RA_WFWG:
2678 remote_arch = "WfWg";
2679 return;
2680 case RA_OS2:
2681 remote_arch = "OS2";
2682 return;
2683 case RA_WIN95:
2684 remote_arch = "Win95";
2685 return;
2686 case RA_WINNT:
2687 remote_arch = "WinNT";
2688 return;
2689 case RA_SAMBA:
2690 remote_arch = "Samba";
2691 return;
2692 default:
2693 ra_type = RA_UNKNOWN;
2694 remote_arch = "UNKNOWN";
2695 break;
2699 /*******************************************************************
2700 Get the remote_arch type.
2701 ********************************************************************/
2702 enum remote_arch_types get_remote_arch(void)
2704 return ra_type;
2706 #endif /* 0 */
2707 #if 0
2708 /*******************************************************************
2709 align a pointer to a multiple of 2 bytes
2710 ********************************************************************/
2711 char *align2(char *q, char *base)
2713 if ((q - base) & 1)
2715 q++;
2717 return q;
2720 void out_ascii(FILE *f, unsigned char *buf,int len)
2722 int i;
2723 for (i=0;i<len;i++)
2725 fprintf(f, "%c", isprint(buf[i])?buf[i]:'.');
2729 void out_data(FILE *f,char *buf1,int len, int per_line)
2731 unsigned char *buf = (unsigned char *)buf1;
2732 int i=0;
2733 if (len<=0)
2735 return;
2738 fprintf(f, "[%03X] ",i);
2739 for (i=0;i<len;)
2741 fprintf(f, "%02X ",(int)buf[i]);
2742 i++;
2743 if (i%(per_line/2) == 0) fprintf(f, " ");
2744 if (i%per_line == 0)
2746 out_ascii(f,&buf[i-per_line ],per_line/2); fprintf(f, " ");
2747 out_ascii(f,&buf[i-per_line/2],per_line/2); fprintf(f, "\n");
2748 if (i<len) fprintf(f, "[%03X] ",i);
2751 if ((i%per_line) != 0)
2753 int n;
2755 n = per_line - (i%per_line);
2756 fprintf(f, " ");
2757 if (n>(per_line/2)) fprintf(f, " ");
2758 while (n--)
2760 fprintf(f, " ");
2762 n = MIN(per_line/2,i%per_line);
2763 out_ascii(f,&buf[i-(i%per_line)],n); fprintf(f, " ");
2764 n = (i%per_line) - n;
2765 if (n>0) out_ascii(f,&buf[i-n],n);
2766 fprintf(f, "\n");
2769 #endif /* 0 */
2771 void print_asc(int level, unsigned char *buf,int len)
2773 int i;
2774 for (i=0;i<len;i++)
2775 DEBUG(level,("%c", isprint(buf[i])?buf[i]:'.'));
2778 void dump_data(int level,char *buf1,int len)
2780 unsigned char *buf = (unsigned char *)buf1;
2781 int i=0;
2782 if (len<=0) return;
2784 DEBUG(level,("[%03X] ",i));
2785 for (i=0;i<len;) {
2786 DEBUG(level,("%02X ",(int)buf[i]));
2787 i++;
2788 if (i%8 == 0) DEBUG(level,(" "));
2789 if (i%16 == 0) {
2790 print_asc(level,&buf[i-16],8); DEBUG(level,(" "));
2791 print_asc(level,&buf[i-8],8); DEBUG(level,("\n"));
2792 if (i<len) DEBUG(level,("[%03X] ",i));
2795 if (i%16) {
2796 int n;
2798 n = 16 - (i%16);
2799 DEBUG(level,(" "));
2800 if (n>8) DEBUG(level,(" "));
2801 while (n--) DEBUG(level,(" "));
2803 n = MIN(8,i%16);
2804 print_asc(level,&buf[i-(i%16)],n); DEBUG(level,(" "));
2805 n = (i%16) - n;
2806 if (n>0) print_asc(level,&buf[i-n],n);
2807 DEBUG(level,("\n"));
2811 char *tab_depth(int depth)
2813 static pstring spaces;
2814 memset(spaces, ' ', depth * 4);
2815 spaces[depth * 4] = 0;
2816 return spaces;
2819 /*****************************************************************************
2820 * Provide a checksum on a string
2822 * Input: s - the null-terminated character string for which the checksum
2823 * will be calculated.
2825 * Output: The checksum value calculated for s.
2827 * ****************************************************************************
2829 int str_checksum(const char *s)
2831 int res = 0;
2832 int c;
2833 int i=0;
2835 while(*s) {
2836 c = *s;
2837 res ^= (c << (i % 15)) ^ (c >> (15-(i%15)));
2838 s++;
2839 i++;
2841 return(res);
2842 } /* str_checksum */
2846 #if 0
2847 /*****************************************************************
2848 zero a memory area then free it. Used to catch bugs faster
2849 *****************************************************************/
2850 void zero_free(void *p, size_t size)
2852 memset(p, 0, size);
2853 free(p);
2857 /*****************************************************************
2858 set our open file limit to a requested max and return the limit
2859 *****************************************************************/
2860 int set_maxfiles(int requested_max)
2862 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
2863 struct rlimit rlp;
2864 int saved_current_limit;
2866 if(getrlimit(RLIMIT_NOFILE, &rlp)) {
2867 DEBUG(0,("set_maxfiles: getrlimit (1) for RLIMIT_NOFILE failed with error %s\n",
2868 strerror(errno) ));
2869 /* just guess... */
2870 return requested_max;
2874 * Set the fd limit to be real_max_open_files + MAX_OPEN_FUDGEFACTOR to
2875 * account for the extra fd we need
2876 * as well as the log files and standard
2877 * handles etc. Save the limit we want to set in case
2878 * we are running on an OS that doesn't support this limit (AIX)
2879 * which always returns RLIM_INFINITY for rlp.rlim_max.
2882 saved_current_limit = rlp.rlim_cur = MIN(requested_max,rlp.rlim_max);
2884 if(setrlimit(RLIMIT_NOFILE, &rlp)) {
2885 DEBUG(0,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d files failed with error %s\n",
2886 (int)rlp.rlim_cur, strerror(errno) ));
2887 /* just guess... */
2888 return saved_current_limit;
2891 if(getrlimit(RLIMIT_NOFILE, &rlp)) {
2892 DEBUG(0,("set_maxfiles: getrlimit (2) for RLIMIT_NOFILE failed with error %s\n",
2893 strerror(errno) ));
2894 /* just guess... */
2895 return saved_current_limit;
2898 #if defined(RLIM_INFINITY)
2899 if(rlp.rlim_cur == RLIM_INFINITY)
2900 return saved_current_limit;
2901 #endif
2903 if((int)rlp.rlim_cur > saved_current_limit)
2904 return saved_current_limit;
2906 return rlp.rlim_cur;
2907 #else /* !defined(HAVE_GETRLIMIT) || !defined(RLIMIT_NOFILE) */
2909 * No way to know - just guess...
2911 return requested_max;
2912 #endif
2914 #endif /* 0 */