Ticket #1649: Prepare for prerelease mc-4.7.0-pre3 (code cleanup)
[midnight-commander.git] / vfs / samba / lib / util.c
blobda2fa83a861de6b262e7662b682795081d92c97e
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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 const 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 const 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(const 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(const 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(const char *user_name)
1996 static pstring server_name;
1997 (void) user_name;
1999 /* use the local machine name as the default */
2000 /* this will be the default if WITH_AUTOMOUNT is not used or fails */
2001 pstrcpy(server_name, local_machine);
2003 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
2005 if (lp_nis_home_map())
2007 int home_server_len;
2008 char *automount_value = automount_lookup(user_name);
2009 home_server_len = strcspn(automount_value,":");
2010 DEBUG(5, ("NIS lookup succeeded. Home server length: %d\n",home_server_len));
2011 if (home_server_len > sizeof(pstring))
2013 home_server_len = sizeof(pstring);
2015 strncpy(server_name, automount_value, home_server_len);
2016 server_name[home_server_len] = '\0';
2018 #endif
2020 DEBUG(4,("Home server: %s\n", server_name));
2022 return server_name;
2025 /*******************************************************************
2026 Patch from jkf@soton.ac.uk
2027 Added this to implement %p (NIS auto-map version of %H)
2028 *******************************************************************/
2029 static char *automount_path(char *user_name)
2031 static pstring server_path;
2033 /* use the passwd entry as the default */
2034 /* this will be the default if WITH_AUTOMOUNT is not used or fails */
2035 /* pstrcpy() copes with get_home_dir() returning NULL */
2036 pstrcpy(server_path, get_home_dir(user_name));
2038 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
2040 if (lp_nis_home_map())
2042 char *home_path_start;
2043 char *automount_value = automount_lookup(user_name);
2044 home_path_start = strchr(automount_value,':');
2045 if (home_path_start != NULL)
2047 DEBUG(5, ("NIS lookup succeeded. Home path is: %s\n",
2048 home_path_start?(home_path_start+1):""));
2049 pstrcpy(server_path, home_path_start+1);
2052 #endif
2054 DEBUG(4,("Home server path: %s\n", server_path));
2056 return server_path;
2060 /*******************************************************************
2061 sub strings with useful parameters
2062 Rewritten by Stefaan A Eeckels <Stefaan.Eeckels@ecc.lu> and
2063 Paul Rippin <pr3245@nopc.eurostat.cec.be>
2064 ********************************************************************/
2065 void standard_sub_basic(char *str)
2067 char *s, *p;
2068 char pidstr[10];
2069 struct passwd *pass;
2070 const char *username = sam_logon_in_ssb ? samlogon_user : sesssetup_user;
2072 for (s = str ; s && *s && (p = strchr(s,'%')); s = p )
2074 switch (*(p+1))
2076 case 'G' :
2078 if ((pass = Get_Pwnam(username))!=NULL)
2080 string_sub(p,"%G",gidtoname(pass->pw_gid));
2082 else
2084 p += 2;
2086 break;
2088 case 'N' : string_sub(p,"%N", automount_server(username)); break;
2089 case 'I' : string_sub(p,"%I", client_addr(Client)); break;
2090 case 'L' : string_sub(p,"%L", local_machine); break;
2091 case 'M' : string_sub(p,"%M", client_name(Client)); break;
2092 case 'R' : string_sub(p,"%R", remote_proto); break;
2093 case 'T' : string_sub(p,"%T", timestring()); break;
2094 case 'U' : string_sub(p,"%U", username); break;
2095 case 'a' : string_sub(p,"%a", remote_arch); break;
2096 case 'd' :
2098 slprintf(pidstr,sizeof(pidstr) - 1, "%d",(int)getpid());
2099 string_sub(p,"%d", pidstr);
2100 break;
2102 case 'h' : string_sub(p,"%h", myhostname); break;
2103 case 'm' : string_sub(p,"%m", remote_machine); break;
2104 case 'v' : string_sub(p,"%v", VERSION); break;
2105 case '$' : /* Expand environment variables */
2107 /* Contributed by Branko Cibej <branko.cibej@hermes.si> */
2108 fstring envname;
2109 char *envval;
2110 char *q, *r;
2111 int copylen;
2113 if (*(p+2) != '(')
2115 p+=2;
2116 break;
2118 if ((q = strchr(p,')')) == NULL)
2120 DEBUG(0,("standard_sub_basic: Unterminated environment \
2121 variable [%s]\n", p));
2122 p+=2;
2123 break;
2126 r = p+3;
2127 copylen = MIN((size_t)(q-r),(size_t)(sizeof(envname)-1));
2128 strncpy(envname,r,copylen);
2129 envname[copylen] = '\0';
2131 if ((envval = getenv(envname)) == NULL)
2133 DEBUG(0,("standard_sub_basic: Environment variable [%s] not set\n",
2134 envname));
2135 p+=2;
2136 break;
2139 copylen = MIN((size_t)(q+1-p),(size_t)(sizeof(envname)-1));
2140 strncpy(envname,p,copylen);
2141 envname[copylen] = '\0';
2142 string_sub(p,envname,envval);
2143 break;
2145 case '\0': p++; break; /* don't run off end if last character is % */
2146 default : p+=2; break;
2149 return;
2153 /****************************************************************************
2154 do some standard substitutions in a string
2155 ****************************************************************************/
2156 void standard_sub(connection_struct *conn,char *str)
2158 char *p, *s;
2159 const char *home;
2161 for (s=str; (p=strchr(s, '%'));s=p) {
2162 switch (*(p+1)) {
2163 case 'H':
2164 if ((home = get_home_dir(conn->user))) {
2165 string_sub(p,"%H",home);
2166 } else {
2167 p += 2;
2169 break;
2171 case 'P':
2172 string_sub(p,"%P",conn->connectpath);
2173 break;
2175 case 'S':
2176 string_sub(p,"%S",
2177 lp_servicename(SNUM(conn)));
2178 break;
2180 case 'g':
2181 string_sub(p,"%g",
2182 gidtoname(conn->gid));
2183 break;
2184 case 'u':
2185 string_sub(p,"%u",conn->user);
2186 break;
2188 /* Patch from jkf@soton.ac.uk Left the %N (NIS
2189 * server name) in standard_sub_basic as it is
2190 * a feature for logon servers, hence uses the
2191 * username. The %p (NIS server path) code is
2192 * here as it is used instead of the default
2193 * "path =" string in [homes] and so needs the
2194 * service name, not the username. */
2195 case 'p':
2196 string_sub(p,"%p",
2197 automount_path(lp_servicename(SNUM(conn))));
2198 break;
2199 case '\0':
2200 p++;
2201 break; /* don't run off the end of the string
2204 default: p+=2;
2205 break;
2209 standard_sub_basic(str);
2214 /*******************************************************************
2215 are two IPs on the same subnet?
2216 ********************************************************************/
2217 BOOL same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask)
2219 uint32 net1,net2,nmask;
2221 nmask = ntohl(mask.s_addr);
2222 net1 = ntohl(ip1.s_addr);
2223 net2 = ntohl(ip2.s_addr);
2225 return((net1 & nmask) == (net2 & nmask));
2229 /****************************************************************************
2230 a wrapper for gethostbyname() that tries with all lower and all upper case
2231 if the initial name fails
2232 ****************************************************************************/
2233 struct hostent *Get_Hostbyname(const char *name)
2235 char *name2 = strdup(name);
2236 struct hostent *ret;
2238 if (!name2)
2240 DEBUG(0,("Memory allocation error in Get_Hostbyname! panic\n"));
2241 exit(0);
2246 * This next test is redundent and causes some systems (with
2247 * broken isalnum() calls) problems.
2248 * JRA.
2251 #if 0
2252 if (!isalnum(*name2))
2254 free(name2);
2255 return(NULL);
2257 #endif /* 0 */
2259 ret = sys_gethostbyname(name2);
2260 if (ret != NULL)
2262 free(name2);
2263 return(ret);
2266 /* try with all lowercase */
2267 strlower(name2);
2268 ret = sys_gethostbyname(name2);
2269 if (ret != NULL)
2271 free(name2);
2272 return(ret);
2275 /* try with all uppercase */
2276 strupper(name2);
2277 ret = sys_gethostbyname(name2);
2278 if (ret != NULL)
2280 free(name2);
2281 return(ret);
2284 /* nothing works :-( */
2285 free(name2);
2286 return(NULL);
2290 /*******************************************************************
2291 turn a uid into a user name
2292 ********************************************************************/
2293 char *uidtoname(uid_t uid)
2295 static char name[40];
2296 struct passwd *pass = getpwuid(uid);
2297 if (pass) return(pass->pw_name);
2298 slprintf(name, sizeof(name) - 1, "%d",(int)uid);
2299 return(name);
2303 /*******************************************************************
2304 turn a gid into a group name
2305 ********************************************************************/
2307 char *gidtoname(gid_t gid)
2309 static char name[40];
2310 struct group *grp = getgrgid(gid);
2311 if (grp) return(grp->gr_name);
2312 slprintf(name,sizeof(name) - 1, "%d",(int)gid);
2313 return(name);
2316 /*******************************************************************
2317 turn a user name into a uid
2318 ********************************************************************/
2319 uid_t nametouid(const char *name)
2321 struct passwd *pass = getpwnam(name);
2322 if (pass) return(pass->pw_uid);
2323 return (uid_t)-1;
2326 /*******************************************************************
2327 something really nasty happened - panic!
2328 ********************************************************************/
2329 void smb_panic(const char *why)
2331 const char *cmd = lp_panic_action();
2332 if (cmd && *cmd) {
2333 system(cmd);
2335 DEBUG(0,("PANIC: %s\n", why));
2336 dbgflush();
2337 abort();
2340 #if 0
2341 /*******************************************************************
2342 a readdir wrapper which just returns the file name
2343 ********************************************************************/
2344 char *readdirname(DIR *p)
2346 SMB_STRUCT_DIRENT *ptr;
2347 char *dname;
2349 if (!p) return(NULL);
2351 ptr = (SMB_STRUCT_DIRENT *)sys_readdir(p);
2352 if (!ptr) return(NULL);
2354 dname = ptr->d_name;
2356 #ifdef NEXT2
2357 if (telldir(p) < 0) return(NULL);
2358 #endif
2360 #ifdef HAVE_BROKEN_READDIR
2361 /* using /usr/ucb/cc is BAD */
2362 dname = dname - 2;
2363 #endif
2366 static pstring buf;
2367 memcpy(buf, dname, NAMLEN(ptr)+1);
2368 dname = buf;
2371 return(dname);
2374 /*******************************************************************
2375 Utility function used to decide if the last component
2376 of a path matches a (possibly wildcarded) entry in a namelist.
2377 ********************************************************************/
2379 BOOL is_in_path(char *name, name_compare_entry *namelist)
2381 pstring last_component;
2382 char *p;
2384 DEBUG(8, ("is_in_path: %s\n", name));
2386 /* if we have no list it's obviously not in the path */
2387 if((namelist == NULL ) || ((namelist != NULL) && (namelist[0].name == NULL)))
2389 DEBUG(8,("is_in_path: no name list.\n"));
2390 return False;
2393 /* Get the last component of the unix name. */
2394 p = strrchr(name, '/');
2395 strncpy(last_component, p ? ++p : name, sizeof(last_component)-1);
2396 last_component[sizeof(last_component)-1] = '\0';
2398 for(; namelist->name != NULL; namelist++)
2400 if(namelist->is_wild)
2403 * Look for a wildcard match. Use the old
2404 * 'unix style' mask match, rather than the
2405 * new NT one.
2407 if (unix_mask_match(last_component, namelist->name, case_sensitive, False))
2409 DEBUG(8,("is_in_path: mask match succeeded\n"));
2410 return True;
2413 else
2415 if((case_sensitive && (strcmp(last_component, namelist->name) == 0))||
2416 (!case_sensitive && (StrCaseCmp(last_component, namelist->name) == 0)))
2418 DEBUG(8,("is_in_path: match succeeded\n"));
2419 return True;
2423 DEBUG(8,("is_in_path: match not found\n"));
2425 return False;
2428 /*******************************************************************
2429 Strip a '/' separated list into an array of
2430 name_compare_enties structures suitable for
2431 passing to is_in_path(). We do this for
2432 speed so we can pre-parse all the names in the list
2433 and don't do it for each call to is_in_path().
2434 namelist is modified here and is assumed to be
2435 a copy owned by the caller.
2436 We also check if the entry contains a wildcard to
2437 remove a potentially expensive call to mask_match
2438 if possible.
2439 ********************************************************************/
2441 void set_namearray(name_compare_entry **ppname_array, char *namelist)
2443 char *name_end;
2444 char *nameptr = namelist;
2445 int num_entries = 0;
2446 int i;
2448 (*ppname_array) = NULL;
2450 if((nameptr == NULL ) || ((nameptr != NULL) && (*nameptr == '\0')))
2451 return;
2453 /* We need to make two passes over the string. The
2454 first to count the number of elements, the second
2455 to split it.
2457 while(*nameptr)
2459 if ( *nameptr == '/' )
2461 /* cope with multiple (useless) /s) */
2462 nameptr++;
2463 continue;
2465 /* find the next / */
2466 name_end = strchr(nameptr, '/');
2468 /* oops - the last check for a / didn't find one. */
2469 if (name_end == NULL)
2470 break;
2472 /* next segment please */
2473 nameptr = name_end + 1;
2474 num_entries++;
2477 if(num_entries == 0)
2478 return;
2480 if(( (*ppname_array) = (name_compare_entry *)malloc(
2481 (num_entries + 1) * sizeof(name_compare_entry))) == NULL)
2483 DEBUG(0,("set_namearray: malloc fail\n"));
2484 return;
2487 /* Now copy out the names */
2488 nameptr = namelist;
2489 i = 0;
2490 while(*nameptr)
2492 if ( *nameptr == '/' )
2494 /* cope with multiple (useless) /s) */
2495 nameptr++;
2496 continue;
2498 /* find the next / */
2499 if ((name_end = strchr(nameptr, '/')) != NULL)
2501 *name_end = 0;
2504 /* oops - the last check for a / didn't find one. */
2505 if(name_end == NULL)
2506 break;
2508 (*ppname_array)[i].is_wild = ((strchr( nameptr, '?')!=NULL) ||
2509 (strchr( nameptr, '*')!=NULL));
2510 if(((*ppname_array)[i].name = strdup(nameptr)) == NULL)
2512 DEBUG(0,("set_namearray: malloc fail (1)\n"));
2513 return;
2516 /* next segment please */
2517 nameptr = name_end + 1;
2518 i++;
2521 (*ppname_array)[i].name = NULL;
2523 return;
2526 /****************************************************************************
2527 routine to free a namearray.
2528 ****************************************************************************/
2530 void free_namearray(name_compare_entry *name_array)
2532 if(name_array == 0)
2533 return;
2535 if(name_array->name != NULL)
2536 free(name_array->name);
2538 free((char *)name_array);
2541 /****************************************************************************
2542 routine to do file locking
2543 ****************************************************************************/
2544 BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
2546 #ifdef HAVE_FCNTL_LOCK
2547 SMB_STRUCT_FLOCK lock;
2548 int ret;
2550 if(lp_ole_locking_compat()) {
2551 SMB_OFF_T mask2= ((SMB_OFF_T)0x3) << (SMB_OFF_T_BITS-4);
2552 SMB_OFF_T mask = (mask2<<2);
2554 /* make sure the count is reasonable, we might kill the lockd otherwise */
2555 count &= ~mask;
2557 /* the offset is often strange - remove 2 of its bits if either of
2558 the top two bits are set. Shift the top ones by two bits. This
2559 still allows OLE2 apps to operate, but should stop lockd from
2560 dieing */
2561 if ((offset & mask) != 0)
2562 offset = (offset & ~mask) | (((offset & mask) >> 2) & mask2);
2563 } else {
2564 SMB_OFF_T mask2 = ((SMB_OFF_T)0x4) << (SMB_OFF_T_BITS-4);
2565 SMB_OFF_T mask = (mask2<<1);
2566 SMB_OFF_T neg_mask = ~mask;
2568 /* interpret negative counts as large numbers */
2569 if (count < 0)
2570 count &= ~mask;
2572 /* no negative offsets */
2573 if(offset < 0)
2574 offset &= ~mask;
2576 /* count + offset must be in range */
2577 while ((offset < 0 || (offset + count < 0)) && mask)
2579 offset &= ~mask;
2580 mask = ((mask >> 1) & neg_mask);
2584 DEBUG(8,("fcntl_lock %d %d %.0f %.0f %d\n",fd,op,(double)offset,(double)count,type));
2586 lock.l_type = type;
2587 lock.l_whence = SEEK_SET;
2588 lock.l_start = offset;
2589 lock.l_len = count;
2590 lock.l_pid = 0;
2592 errno = 0;
2594 ret = fcntl(fd,op,&lock);
2595 if (errno == EFBIG)
2597 if( DEBUGLVL( 0 ))
2599 dbgtext("fcntl_lock: WARNING: lock request at offset %.0f, length %.0f returned\n", (double)offset,(double)count);
2600 dbgtext("a 'file too large' error. This can happen when using 64 bit lock offsets\n");
2601 dbgtext("on 32 bit NFS mounted file systems. Retrying with 32 bit truncated length.\n");
2603 /* 32 bit NFS file system, retry with smaller offset */
2604 errno = 0;
2605 lock.l_len = count & 0xffffffff;
2606 ret = fcntl(fd,op,&lock);
2609 if (errno != 0)
2610 DEBUG(3,("fcntl lock gave errno %d (%s)\n",errno,strerror(errno)));
2612 /* a lock query */
2613 if (op == SMB_F_GETLK)
2615 if ((ret != -1) &&
2616 (lock.l_type != F_UNLCK) &&
2617 (lock.l_pid != 0) &&
2618 (lock.l_pid != getpid()))
2620 DEBUG(3,("fd %d is locked by pid %d\n",fd,(int)lock.l_pid));
2621 return(True);
2624 /* it must be not locked or locked by me */
2625 return(False);
2628 /* a lock set or unset */
2629 if (ret == -1)
2631 DEBUG(3,("lock failed at offset %.0f count %.0f op %d type %d (%s)\n",
2632 (double)offset,(double)count,op,type,strerror(errno)));
2634 /* perhaps it doesn't support this sort of locking?? */
2635 if (errno == EINVAL)
2637 DEBUG(3,("locking not supported? returning True\n"));
2638 return(True);
2641 return(False);
2644 /* everything went OK */
2645 DEBUG(8,("Lock call successful\n"));
2647 return(True);
2648 #else
2649 return(False);
2650 #endif
2653 /*******************************************************************
2654 is the name specified one of my netbios names
2655 returns true is it is equal, false otherwise
2656 ********************************************************************/
2657 BOOL is_myname(char *s)
2659 int n;
2660 BOOL ret = False;
2662 for (n=0; my_netbios_names[n]; n++) {
2663 if (strequal(my_netbios_names[n], s))
2664 ret=True;
2666 DEBUG(8, ("is_myname(\"%s\") returns %d\n", s, ret));
2667 return(ret);
2669 #endif /* 0 */
2670 #if 0 /* Can be useful one day */
2671 /*******************************************************************
2672 set the horrid remote_arch string based on an enum.
2673 ********************************************************************/
2674 void set_remote_arch(enum remote_arch_types type)
2676 ra_type = type;
2677 switch( type )
2679 case RA_WFWG:
2680 remote_arch = "WfWg";
2681 return;
2682 case RA_OS2:
2683 remote_arch = "OS2";
2684 return;
2685 case RA_WIN95:
2686 remote_arch = "Win95";
2687 return;
2688 case RA_WINNT:
2689 remote_arch = "WinNT";
2690 return;
2691 case RA_SAMBA:
2692 remote_arch = "Samba";
2693 return;
2694 default:
2695 ra_type = RA_UNKNOWN;
2696 remote_arch = "UNKNOWN";
2697 break;
2701 /*******************************************************************
2702 Get the remote_arch type.
2703 ********************************************************************/
2704 enum remote_arch_types get_remote_arch(void)
2706 return ra_type;
2708 #endif /* 0 */
2709 #if 0
2710 /*******************************************************************
2711 align a pointer to a multiple of 2 bytes
2712 ********************************************************************/
2713 char *align2(char *q, char *base)
2715 if ((q - base) & 1)
2717 q++;
2719 return q;
2722 void out_ascii(FILE *f, unsigned char *buf,int len)
2724 int i;
2725 for (i=0;i<len;i++)
2727 fprintf(f, "%c", isprint(buf[i])?buf[i]:'.');
2731 void out_data(FILE *f,char *buf1,int len, int per_line)
2733 unsigned char *buf = (unsigned char *)buf1;
2734 int i=0;
2735 if (len<=0)
2737 return;
2740 fprintf(f, "[%03X] ",i);
2741 for (i=0;i<len;)
2743 fprintf(f, "%02X ",(int)buf[i]);
2744 i++;
2745 if (i%(per_line/2) == 0) fprintf(f, " ");
2746 if (i%per_line == 0)
2748 out_ascii(f,&buf[i-per_line ],per_line/2); fprintf(f, " ");
2749 out_ascii(f,&buf[i-per_line/2],per_line/2); fprintf(f, "\n");
2750 if (i<len) fprintf(f, "[%03X] ",i);
2753 if ((i%per_line) != 0)
2755 int n;
2757 n = per_line - (i%per_line);
2758 fprintf(f, " ");
2759 if (n>(per_line/2)) fprintf(f, " ");
2760 while (n--)
2762 fprintf(f, " ");
2764 n = MIN(per_line/2,i%per_line);
2765 out_ascii(f,&buf[i-(i%per_line)],n); fprintf(f, " ");
2766 n = (i%per_line) - n;
2767 if (n>0) out_ascii(f,&buf[i-n],n);
2768 fprintf(f, "\n");
2771 #endif /* 0 */
2773 void print_asc(int level, unsigned char *buf,int len)
2775 int i;
2776 for (i=0;i<len;i++)
2777 DEBUG(level,("%c", isprint(buf[i])?buf[i]:'.'));
2780 void dump_data(int level,char *buf1,int len)
2782 unsigned char *buf = (unsigned char *)buf1;
2783 int i=0;
2784 if (len<=0) return;
2786 DEBUG(level,("[%03X] ",i));
2787 for (i=0;i<len;) {
2788 DEBUG(level,("%02X ",(int)buf[i]));
2789 i++;
2790 if (i%8 == 0) DEBUG(level,(" "));
2791 if (i%16 == 0) {
2792 print_asc(level,&buf[i-16],8); DEBUG(level,(" "));
2793 print_asc(level,&buf[i-8],8); DEBUG(level,("\n"));
2794 if (i<len) DEBUG(level,("[%03X] ",i));
2797 if (i%16) {
2798 int n;
2800 n = 16 - (i%16);
2801 DEBUG(level,(" "));
2802 if (n>8) DEBUG(level,(" "));
2803 while (n--) DEBUG(level,(" "));
2805 n = MIN(8,i%16);
2806 print_asc(level,&buf[i-(i%16)],n); DEBUG(level,(" "));
2807 n = (i%16) - n;
2808 if (n>0) print_asc(level,&buf[i-n],n);
2809 DEBUG(level,("\n"));
2813 /*****************************************************************************
2814 * Provide a checksum on a string
2816 * Input: s - the null-terminated character string for which the checksum
2817 * will be calculated.
2819 * Output: The checksum value calculated for s.
2821 * ****************************************************************************
2823 int str_checksum(const char *s)
2825 int res = 0;
2826 int c;
2827 int i=0;
2829 while(*s) {
2830 c = *s;
2831 res ^= (c << (i % 15)) ^ (c >> (15-(i%15)));
2832 s++;
2833 i++;
2835 return(res);
2836 } /* str_checksum */
2840 #if 0
2841 /*****************************************************************
2842 zero a memory area then free it. Used to catch bugs faster
2843 *****************************************************************/
2844 void zero_free(void *p, size_t size)
2846 memset(p, 0, size);
2847 free(p);
2851 /*****************************************************************
2852 set our open file limit to a requested max and return the limit
2853 *****************************************************************/
2854 int set_maxfiles(int requested_max)
2856 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
2857 struct rlimit rlp;
2858 int saved_current_limit;
2860 if(getrlimit(RLIMIT_NOFILE, &rlp)) {
2861 DEBUG(0,("set_maxfiles: getrlimit (1) for RLIMIT_NOFILE failed with error %s\n",
2862 strerror(errno) ));
2863 /* just guess... */
2864 return requested_max;
2868 * Set the fd limit to be real_max_open_files + MAX_OPEN_FUDGEFACTOR to
2869 * account for the extra fd we need
2870 * as well as the log files and standard
2871 * handles etc. Save the limit we want to set in case
2872 * we are running on an OS that doesn't support this limit (AIX)
2873 * which always returns RLIM_INFINITY for rlp.rlim_max.
2876 saved_current_limit = rlp.rlim_cur = MIN(requested_max,rlp.rlim_max);
2878 if(setrlimit(RLIMIT_NOFILE, &rlp)) {
2879 DEBUG(0,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d files failed with error %s\n",
2880 (int)rlp.rlim_cur, strerror(errno) ));
2881 /* just guess... */
2882 return saved_current_limit;
2885 if(getrlimit(RLIMIT_NOFILE, &rlp)) {
2886 DEBUG(0,("set_maxfiles: getrlimit (2) for RLIMIT_NOFILE failed with error %s\n",
2887 strerror(errno) ));
2888 /* just guess... */
2889 return saved_current_limit;
2892 #if defined(RLIM_INFINITY)
2893 if(rlp.rlim_cur == RLIM_INFINITY)
2894 return saved_current_limit;
2895 #endif
2897 if((int)rlp.rlim_cur > saved_current_limit)
2898 return saved_current_limit;
2900 return rlp.rlim_cur;
2901 #else /* !defined(HAVE_GETRLIMIT) || !defined(RLIMIT_NOFILE) */
2903 * No way to know - just guess...
2905 return requested_max;
2906 #endif
2908 #endif /* 0 */