2 Unix SMB/Netbios implementation.
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.
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.
39 #if defined(GROUP_OBJ)
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 */
56 #undef Realloc /* SSLeay defines this and samba has a function of this name */
61 extern int DEBUGLEVEL
;
63 int Protocol
= PROTOCOL_COREPLUS
;
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 */
72 /* this is used by the chaining code */
73 const int chain_size
= 0;
79 case handling on filenames
81 const int case_default
= CASE_LOWER
;
84 /* the following control case operations - they are put here so the
85 client can link easily */
88 BOOL use_mangled_map
= False
;
89 BOOL short_case_preserve
;
93 static const char *remote_machine
= "";
94 static const char *local_machine
= "";
95 static const char *remote_arch
= "UNKNOWN";
97 static enum remote_arch_types ra_type
= RA_UNKNOWN
;
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
= "";
110 char **my_netbios_names
;
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)
121 if ((p
= getenv("MC_TMPDIR")) || (p
= getenv("TMPDIR"))) {
127 /****************************************************************************
128 determine whether we are in the specified group
129 ****************************************************************************/
131 BOOL
in_group(gid_t group
, gid_t current_gid
, int ngroups
, gid_t
*groups
)
135 if (group
== current_gid
) return(True
);
137 for (i
=0;i
<ngroups
;i
++)
138 if (group
== groups
[i
])
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"));
158 while ((*p
) && isdigit((int)*p
))
163 if (strchr(c
, *p
) == NULL
)
165 DEBUG(5, ("Atoic: no separator characters (%s) not found\n", c
));
172 /*************************************************************************
173 reads a list of numbers
174 *************************************************************************/
175 char *get_numlist(char *p
, uint32
**num
, int *count
)
179 if (num
== NULL
|| count
== NULL
)
187 while ((p
= Atoic(p
, &val
, ":,")) != NULL
&& (*p
) != ':')
189 (*num
) = Realloc((*num
), ((*count
)+1) * sizeof(uint32
));
194 (*num
)[(*count
)] = val
;
202 /*******************************************************************
203 copy an IP address from one buffer to another
204 ********************************************************************/
205 void putip(void *dest
,void *src
)
211 #define TRUNCATE_NETBIOS_NAME 1
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
220 the netbios name (NOT necessarily null-terminated) is truncated to 15
223 ******************************************************************/
224 char *dns_to_netbios_name(char *dns_name
)
226 static char netbios_name
[16];
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
] == '.')
245 #endif /* TRUNCATE_NETBIOS_NAME */
251 /****************************************************************************
252 interpret the weird netbios "name". Return the name type
253 ****************************************************************************/
254 static int name_interpret(char *in
,char *out
)
257 int len
= (*in
++) / 2;
261 if (len
> 30 || len
<1) return(0);
265 if (in
[0] < 'A' || in
[0] > 'P' || in
[1] < 'A' || in
[1] > 'P') {
269 *out
= ((in
[0]-'A')<<4) + (in
[1]-'A');
277 /* Handle any scope names */
280 *out
++ = '.'; /* Scope names are separated by periods */
281 len
= *(unsigned char *)in
++;
282 StrnCpy(out
, in
, len
);
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
)
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)
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. */
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';
327 /* Add the scope string. */
328 for( i
= 0, len
= 0; NULL
!= global_scope
; i
++, len
++ )
330 switch( global_scope
[i
] )
336 return( name_len(Out
) );
343 p
[len
+1] = global_scope
[i
];
348 return( name_len(Out
) );
351 /*******************************************************************
352 check if a file exists
353 ********************************************************************/
354 BOOL
file_exist(char *fname
,SMB_STRUCT_STAT
*sbuf
)
357 if (!sbuf
) sbuf
= &st
;
359 if (sys_stat(fname
,sbuf
) != 0)
362 return(S_ISREG(sbuf
->st_mode
));
365 /*******************************************************************
366 check a files mod time
367 ********************************************************************/
368 time_t file_modtime(char *fname
)
372 if (sys_stat(fname
,&st
) != 0)
378 /*******************************************************************
379 check if a directory exists
380 ********************************************************************/
381 BOOL
directory_exist(char *dname
,SMB_STRUCT_STAT
*st
)
388 if (sys_stat(dname
,st
) != 0)
391 ret
= S_ISDIR(st
->st_mode
);
397 /*******************************************************************
398 returns the size in bytes of the named file
399 ********************************************************************/
400 SMB_OFF_T
file_size(char *file_name
)
404 if(sys_stat(file_name
,&buf
) != 0)
405 return (SMB_OFF_T
)-1;
410 /*******************************************************************
411 return a string representing an attribute for a file
412 ********************************************************************/
413 char *attrib_string(uint16 mode
)
415 static fstring attrstr
;
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");
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
,'/','\\');
446 /*******************************************************************
447 show a smb message structure
448 ********************************************************************/
449 void show_msg(char *buf
)
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",
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;
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
)
504 buf
[1] = (len
&0x10000)>>16;
505 buf
[2] = (len
&0xFF00)>>8;
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
);
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
)
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
);
576 /*******************************************************************
577 reduce a file name, removing .. elements.
578 ********************************************************************/
579 void dos_clean_name(char *s
)
583 DEBUG(3,("dos_clean_name [%s]\n",s
));
585 /* remove any double slashes */
586 string_sub(s
, "\\\\", "\\");
588 while ((p
= strstr(s
,"\\..\\")) != NULL
)
595 if ((p
=strrchr(s
,'\\')) != NULL
)
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
)
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
);
626 while ((p
= strstr(s
,"/../")) != NULL
)
633 if ((p
=strrchr(s
,'/')) != NULL
)
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
)
660 BOOL relative
= (*s
!= '/');
662 *dir2
= *wd
= *base_name
= *newname
= 0;
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
));
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
,'/');
693 DEBUG(0,("couldn't getwd for %s %s\n",s
,dir
));
697 if (dos_ChDir(dir
) != 0)
699 DEBUG(0,("couldn't chdir to %s\n",dir
));
703 if (!dos_GetWd(dir2
))
705 DEBUG(0,("couldn't getwd for %s\n",dir
));
710 if (p
&& (p
!= base_name
))
713 if (strcmp(p
+1,".")==0)
715 if (strcmp(p
+1,"..")==0)
719 if (dos_ChDir(base_name
) != 0)
722 DEBUG(3,("couldn't chdir for %s %s basename=%s\n",s
,dir
,base_name
));
726 if (!dos_GetWd(newname
))
729 DEBUG(2,("couldn't get wd for %s %s\n",s
,dir2
));
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] == '/')
744 if (strncmp(newname
,dir2
,l
) != 0)
747 DEBUG(2,("Bad access attempt? s=%s dir=%s newname=%s l=%d\n",s
,dir2
,newname
,(int)l
));
753 if (newname
[l
] == '/')
754 pstrcpy(s
,newname
+ l
+ 1);
756 pstrcpy(s
,newname
+l
);
767 DEBUG(3,("reduced to %s\n",s
));
773 /****************************************************************************
775 ****************************************************************************/
776 static void expand_one(char *Mask
,int len
)
779 while ((p1
= strchr(Mask
,'*')) != NULL
)
781 int lfill
= (len
+1) - strlen(Mask
);
785 memset(tmp
+l1
,'?',lfill
);
786 pstrcpy(tmp
+ l1
+ lfill
,Mask
+ l1
+ 1);
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
,'\\');
815 /****************************************************************************
816 expand a wildcard expression, replacing *s with ?s
817 ****************************************************************************/
818 void expand_mask(char *Mask
,BOOL doext
)
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
)
846 if (strlen(mbeg
) > 8)
848 pstrcpy(mext
,mbeg
+ 8);
854 pstrcpy(mbeg
,"????????");
855 if ((*mext
== 0) && doext
&& !hasdot
)
858 if (strequal(mbeg
,"*") && *mext
==0)
866 pstrcpy(Mask
,dirpart
);
867 if (*dirpart
|| absolute
) pstrcat(Mask
,"\\");
872 DEBUG(6,("Mask expanded to [%s]\n",Mask
));
876 /****************************************************************************
878 ****************************************************************************/
879 void make_dir_struct(char *buf
,char *mask
,char *fname
,SMB_OFF_T size
,int mode
,time_t date
)
886 if ((mode
& aDIR
) != 0)
889 memset(buf
+1,' ',11);
890 if ((p
= strchr(mask2
,'.')) != NULL
)
893 memcpy(buf
+1,mask2
,MIN(strlen(mask2
),8));
894 memcpy(buf
+9,p
+1,MIN(strlen(p
+1),3));
898 memcpy(buf
+1,mask2
,MIN(strlen(mask2
),11));
900 memset(buf
+21,'\0',DIR_STRUCT_SIZE
-21);
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);
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)
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 */
923 fd
= sys_open("/dev/null",O_RDWR
,0);
924 if (fd
< 0) fd
= sys_open("/dev/null",O_WRONLY
,0);
926 DEBUG(0,("Cannot open /dev/null\n"));
930 DEBUG(0,("Didn't get file descriptor %d\n",i
));
937 /****************************************************************************
938 Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
942 ****************************************************************************/
943 int set_blocking(int fd
, BOOL set
)
947 #define FLAG_TO_SET O_NONBLOCK
950 #define FLAG_TO_SET O_NDELAY
952 #define FLAG_TO_SET FNDELAY
956 if((val
= fcntl(fd
, F_GETFL
, 0)) == -1)
958 if(set
) /* Turn blocking on - ie. clear nonblock flag */
962 return fcntl( fd
, F_SETFL
, val
);
967 /*******************************************************************
968 find the difference in milliseconds between two struct timeval
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);
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
;
989 DEBUG(4,("transfer_file n=%.0f (head=%d) called\n",(double)n
,headlen
));
992 size
= lp_readsize();
993 size
= MAX(size
,1024);
996 while (!buf
&& size
>0) {
997 buf
= (char *)Realloc(buf
,size
+8);
1002 DEBUG(0,("Cannot allocate transfer buffer!\n"));
1006 abuf
= buf
+ (align
%8);
1013 int s
= (int)MIN(n
,(SMB_OFF_T
)size
);
1018 if (header
&& (headlen
>= MIN(s
,1024))) {
1028 if (header
&& headlen
> 0)
1030 ret
= MIN(headlen
,size
);
1031 memcpy(buf1
,header
,ret
);
1034 if (headlen
<= 0) header
= NULL
;
1038 ret
+= read(infd
,buf1
+ret
,s
-ret
);
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 */
1046 transfer_file(infd
,-1,n
-(ret
+headlen
),NULL
,0,0);
1048 if (ret
<= 0 || ret2
!= ret
)
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)
1067 memcpy(p
,buf
+ofs
,2);
1070 DEBUG(5,("name ptr to pos %d from %d is %s\n",l
,ofs
,buf
+l
));
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
);
1085 if (d
< -50 || d
> 50) return(0);
1086 return(name_interpret(p
,name
));
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
;
1099 /* If the two high bits of the byte are set, return 2. */
1100 if (0xC0 == (*s
& 0xC0))
1103 /* Add up the length bytes. */
1104 for (len
= 1; (*s
); s
+= (*s
) + 1) {
1106 SMB_ASSERT(len
< 80);
1113 /*******************************************************************
1114 sleep for a specified number of milliseconds
1115 ********************************************************************/
1119 struct timeval tval
,t1
,t2
;
1126 tval
.tv_sec
= (t
-tdiff
)/1000;
1127 tval
.tv_usec
= 1000*((t
-tdiff
)%1000);
1131 sys_select(0,&fds
,&tval
);
1134 tdiff
= TvalDiff(&t1
,&t2
);
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
)
1148 for( p
= regexp
; *p
&& *str
; ) {
1155 /* Look for a character matching
1156 the one after the '*' */
1159 return True
; /* Automatic match */
1161 while(*str
&& (case_sig
? (*p
!= *str
) : (toupper(*p
)!=toupper(*str
))))
1163 if(unix_do_match(str
,p
,case_sig
))
1177 if(toupper(*str
) != toupper(*p
))
1187 if (!*p
&& str
[0] == '.' && str
[1] == 0)
1190 if (!*str
&& *p
== '?')
1192 while (*p
== '?') p
++;
1196 if(!*str
&& (*p
== '*' && p
[1] == '\0'))
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
)
1213 fstring ebase
,eext
,sbase
,sext
;
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
,'.')) {
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
));
1238 if ((p
=strrchr(p1
,'.'))) {
1247 if (!strequal(p2
,".") && !strequal(p2
,"..") && (p
=strrchr(p2
,'.'))) {
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
));
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
)
1275 for( p
= regexp
; *p
&& *str
; ) {
1282 /* Look for a character matching
1283 the one after the '*' */
1286 return True
; /* Automatic match */
1288 while(*str
&& (case_sig
? (*p
!= *str
) : (toupper(*p
)!=toupper(*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
))))
1294 str
--; /* We've eaten the match char after the '*' */
1295 if(do_match(str
,p
,case_sig
)) {
1312 if(toupper(*str
) != toupper(*p
)) {
1324 if (!*p
&& str
[0] == '.' && str
[1] == 0) {
1328 if (!*str
&& *p
== '?') {
1334 if(!*str
&& (*p
== '*' && p
[1] == '\0')) {
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
)
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
);
1364 /* a special case for 16 bit apps */
1365 if (strequal(t_pattern
,"????????.???"))
1366 pstrcpy(t_pattern
,"*");
1370 * Handle broken clients that send us old 8.3 format.
1372 string_sub(t_pattern
,"????????","*");
1373 string_sub(t_pattern
,".???",".*");
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
))
1386 if (!strchr(t_filename
,'.')) {
1387 pstrcat(t_filename
,".");
1391 /* Remove any *? and ** as they are meaningless */
1392 string_sub(t_pattern
, "*?", "*");
1393 string_sub(t_pattern
, "**", "*");
1395 if (strequal(t_pattern
,"*"))
1398 DEBUG(8,("mask_match str=<%s> regexp=<%s>, case_sig = %d\n", t_filename
, t_pattern
, case_sig
));
1402 * Match each component of the regexp, split up by '.'
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
);
1424 for( cp1
= te_pattern
, cp2
= te_filename
; cp1
;) {
1425 fp
= strchr(cp2
, '.');
1428 rp
= strchr(cp1
, '.');
1432 if(cp1
[strlen(cp1
)-1] == '*')
1433 last_wcard_was_star
= True
;
1435 last_wcard_was_star
= False
;
1437 if(!do_match(cp2
, cp1
, case_sig
))
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. */
1447 for(i
= 0; i
< num_path_components
- num_regexp_components
; i
++) {
1448 fp
= strchr(cp2
, '.');
1452 if((cp1
!= NULL
) && do_match( cp2
, cp1
, case_sig
)) {
1453 cp2
= fp
? fp
+ 1 : "";
1456 cp2
= fp
? fp
+ 1 : "";
1458 num_path_components
-= i
;
1461 if(cp1
== NULL
&& ((*cp2
== '\0') || last_wcard_was_star
))
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
, "?"))
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
, "?.*"))
1492 if ((p
= strrchr (t_pattern
, '.'))) {
1494 * Wildcard has a suffix.
1497 fstrcpy (ebase
, t_pattern
);
1499 fstrcpy (eext
, p
+ 1);
1501 /* pattern ends in DOT: treat as if there is no DOT */
1503 if (strequal (ebase
, "*"))
1508 * No suffix for wildcard.
1510 fstrcpy (ebase
, t_pattern
);
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 */
1525 * Filename has an extension.
1528 fstrcpy (sbase
, t_filename
);
1529 fstrcpy (sext
, p
+ 1);
1531 matched
= do_match(sbase
, ebase
, case_sig
)
1532 && do_match(sext
, eext
, case_sig
);
1534 /* pattern has no extension */
1535 /* Really: match complete filename with pattern ??? means exactly 3 chars */
1536 matched
= do_match(str
, ebase
, case_sig
);
1540 * Filename has no extension.
1542 fstrcpy (sbase
, t_filename
);
1545 /* pattern has extension */
1546 matched
= do_match(sbase
, ebase
, case_sig
)
1547 && do_match(sext
, eext
, case_sig
);
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
1558 /* a? matches aa and a in w95 */
1559 fstrcat (sbase
, ".");
1560 matched
= do_match(sbase
, ebase
, case_sig
);
1568 DEBUG(8,("mask_match returning %d\n", matched
));
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
1586 #ifdef HAVE_FTRUNCATE_EXTEND
1587 return sys_ftruncate(fd
, len
);
1591 SMB_OFF_T currpos
= sys_lseek(fd
, (SMB_OFF_T
)0, SEEK_CUR
);
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
1599 if(sys_fstat(fd
, &st
)<0)
1603 if (S_ISFIFO(st
.st_mode
))
1607 if(st
.st_size
== len
)
1609 if(st
.st_size
> len
)
1610 return sys_ftruncate(fd
, len
);
1612 if(sys_lseek(fd
, len
-1, SEEK_SET
) != len
-1)
1614 if(write(fd
, &c
, 1)!=1)
1616 /* Seek to where we were */
1617 if(sys_lseek(fd
, currpos
, SEEK_SET
) != currpos
)
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
);
1637 /****************************************************************************
1638 expand a pointer to be a particular size
1639 ****************************************************************************/
1640 void *Realloc(void *p
,size_t size
)
1646 DEBUG(5,("Realloc asked for 0 bytes\n"));
1651 ret
= (void *)malloc(size
);
1653 ret
= (void *)realloc(p
,size
);
1658 smb_mem_write_info(ret
, dbf
);
1663 DEBUG(0,("Memory allocation error: failed to expand to %d bytes\n",(int)size
));
1669 /****************************************************************************
1670 get my own name and IP
1671 ****************************************************************************/
1672 BOOL
get_myname(char *my_name
,struct in_addr
*ip
)
1679 /* get my host name */
1680 if (gethostname(hostname
, sizeof(hostname
)) == -1)
1682 DEBUG(0,("gethostname failed\n"));
1686 /* Ensure null termination. */
1687 hostname
[sizeof(hostname
)-1] = '\0';
1690 if ((hp
= Get_Hostbyname(hostname
)) == 0)
1692 DEBUG(0,( "Get_Hostbyname: Unknown host %s\n",hostname
));
1698 /* split off any parts after an initial . */
1699 char *p
= strchr(hostname
,'.');
1702 fstrcpy(my_name
,hostname
);
1706 putip((char *)ip
,(char *)hp
->h_addr
);
1712 /****************************************************************************
1713 true if two IP addresses are equal
1714 ****************************************************************************/
1715 BOOL
ip_equal(struct in_addr ip1
,struct in_addr ip2
)
1718 a1
= ntohl(ip1
.s_addr
);
1719 a2
= ntohl(ip2
.s_addr
);
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
));
1748 /****************************************************************************
1749 interpret an internet address or name into an IP address in 4 byte form
1750 ****************************************************************************/
1751 uint32
interpret_addr(const char *str
)
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 */
1767 res
= inet_addr(str
);
1769 /* otherwise assume it's a network name of some sort and use
1771 if ((hp
= Get_Hostbyname(str
)) == 0) {
1772 DEBUG(3,("Get_Hostbyname: Unknown host. %s\n",str
));
1775 if(hp
->h_addr
== NULL
) {
1776 DEBUG(3,("Get_Hostbyname: host address is invalid for host %s\n",str
));
1779 putip((char *)&res
,(char *)hp
->h_addr
);
1782 if (res
== (uint32
)-1) return(0);
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
);
1798 /*******************************************************************
1799 check if an IP is the 0.0.0.0
1800 ******************************************************************/
1801 BOOL
zero_ip(struct in_addr ip
)
1804 putip((char *)&a
,(char *)&ip
);
1809 /*******************************************************************
1810 matchname - determine if host name matches IP address
1811 ******************************************************************/
1812 BOOL
matchname(char *remotehost
,struct in_addr addr
)
1817 if ((hp
= Get_Hostbyname(remotehost
)) == 0) {
1818 DEBUG(0,("Get_Hostbyname(%s): lookup failure.\n", remotehost
));
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
));
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)
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
));
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
)
1866 while(*p
&& !isspace(*p
))
1868 while(*p
&& isspace(*p
))
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];
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
, "");
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
));
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
)));
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
);
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
));
1986 #endif /* WITH_NISPLUS_HOME */
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
;
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';
2020 DEBUG(4,("Home server: %s\n", 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);
2054 DEBUG(4,("Home server path: %s\n", 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
)
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
)
2078 if ((pass
= Get_Pwnam(username
))!=NULL
)
2080 string_sub(p
,"%G",gidtoname(pass
->pw_gid
));
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;
2098 slprintf(pidstr
,sizeof(pidstr
) - 1, "%d",(int)getpid());
2099 string_sub(p
,"%d", pidstr
);
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> */
2118 if ((q
= strchr(p
,')')) == NULL
)
2120 DEBUG(0,("standard_sub_basic: Unterminated environment \
2121 variable [%s]\n", p
));
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",
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
);
2145 case '\0': p
++; break; /* don't run off end if last character is % */
2146 default : p
+=2; break;
2153 /****************************************************************************
2154 do some standard substitutions in a string
2155 ****************************************************************************/
2156 void standard_sub(connection_struct
*conn
,char *str
)
2161 for (s
=str
; (p
=strchr(s
, '%'));s
=p
) {
2164 if ((home
= get_home_dir(conn
->user
))) {
2165 string_sub(p
,"%H",home
);
2172 string_sub(p
,"%P",conn
->connectpath
);
2177 lp_servicename(SNUM(conn
)));
2182 gidtoname(conn
->gid
));
2185 string_sub(p
,"%u",conn
->user
);
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. */
2197 automount_path(lp_servicename(SNUM(conn
))));
2201 break; /* don't run off the end of the string
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
;
2240 DEBUG(0,("Memory allocation error in Get_Hostbyname! panic\n"));
2246 * This next test is redundent and causes some systems (with
2247 * broken isalnum() calls) problems.
2252 if (!isalnum(*name2
))
2259 ret
= sys_gethostbyname(name2
);
2266 /* try with all lowercase */
2268 ret
= sys_gethostbyname(name2
);
2275 /* try with all uppercase */
2277 ret
= sys_gethostbyname(name2
);
2284 /* nothing works :-( */
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
);
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
);
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
);
2326 /*******************************************************************
2327 something really nasty happened - panic!
2328 ********************************************************************/
2329 void smb_panic(const char *why
)
2331 const char *cmd
= lp_panic_action();
2335 DEBUG(0,("PANIC: %s\n", why
));
2341 /*******************************************************************
2342 a readdir wrapper which just returns the file name
2343 ********************************************************************/
2344 char *readdirname(DIR *p
)
2346 SMB_STRUCT_DIRENT
*ptr
;
2349 if (!p
) return(NULL
);
2351 ptr
= (SMB_STRUCT_DIRENT
*)sys_readdir(p
);
2352 if (!ptr
) return(NULL
);
2354 dname
= ptr
->d_name
;
2357 if (telldir(p
) < 0) return(NULL
);
2360 #ifdef HAVE_BROKEN_READDIR
2361 /* using /usr/ucb/cc is BAD */
2367 memcpy(buf
, dname
, NAMLEN(ptr
)+1);
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
;
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"));
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
2407 if (unix_mask_match(last_component
, namelist
->name
, case_sensitive
, False
))
2409 DEBUG(8,("is_in_path: mask match succeeded\n"));
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"));
2423 DEBUG(8,("is_in_path: match not found\n"));
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
2439 ********************************************************************/
2441 void set_namearray(name_compare_entry
**ppname_array
, char *namelist
)
2444 char *nameptr
= namelist
;
2445 int num_entries
= 0;
2448 (*ppname_array
) = NULL
;
2450 if((nameptr
== NULL
) || ((nameptr
!= NULL
) && (*nameptr
== '\0')))
2453 /* We need to make two passes over the string. The
2454 first to count the number of elements, the second
2459 if ( *nameptr
== '/' )
2461 /* cope with multiple (useless) /s) */
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
)
2472 /* next segment please */
2473 nameptr
= name_end
+ 1;
2477 if(num_entries
== 0)
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"));
2487 /* Now copy out the names */
2492 if ( *nameptr
== '/' )
2494 /* cope with multiple (useless) /s) */
2498 /* find the next / */
2499 if ((name_end
= strchr(nameptr
, '/')) != NULL
)
2504 /* oops - the last check for a / didn't find one. */
2505 if(name_end
== NULL
)
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"));
2516 /* next segment please */
2517 nameptr
= name_end
+ 1;
2521 (*ppname_array
)[i
].name
= NULL
;
2526 /****************************************************************************
2527 routine to free a namearray.
2528 ****************************************************************************/
2530 void free_namearray(name_compare_entry
*name_array
)
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
;
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 */
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
2561 if ((offset
& mask
) != 0)
2562 offset
= (offset
& ~mask
) | (((offset
& mask
) >> 2) & mask2
);
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 */
2572 /* no negative offsets */
2576 /* count + offset must be in range */
2577 while ((offset
< 0 || (offset
+ count
< 0)) && 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
));
2587 lock
.l_whence
= SEEK_SET
;
2588 lock
.l_start
= offset
;
2594 ret
= fcntl(fd
,op
,&lock
);
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 */
2605 lock
.l_len
= count
& 0xffffffff;
2606 ret
= fcntl(fd
,op
,&lock
);
2610 DEBUG(3,("fcntl lock gave errno %d (%s)\n",errno
,strerror(errno
)));
2613 if (op
== SMB_F_GETLK
)
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
));
2624 /* it must be not locked or locked by me */
2628 /* a lock set or unset */
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"));
2644 /* everything went OK */
2645 DEBUG(8,("Lock call successful\n"));
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
)
2662 for (n
=0; my_netbios_names
[n
]; n
++) {
2663 if (strequal(my_netbios_names
[n
], s
))
2666 DEBUG(8, ("is_myname(\"%s\") returns %d\n", s
, ret
));
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
)
2680 remote_arch
= "WfWg";
2683 remote_arch
= "OS2";
2686 remote_arch
= "Win95";
2689 remote_arch
= "WinNT";
2692 remote_arch
= "Samba";
2695 ra_type
= RA_UNKNOWN
;
2696 remote_arch
= "UNKNOWN";
2701 /*******************************************************************
2702 Get the remote_arch type.
2703 ********************************************************************/
2704 enum remote_arch_types
get_remote_arch(void)
2710 /*******************************************************************
2711 align a pointer to a multiple of 2 bytes
2712 ********************************************************************/
2713 char *align2(char *q
, char *base
)
2722 void out_ascii(FILE *f
, unsigned char *buf
,int len
)
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
;
2740 fprintf(f
, "[%03X] ",i
);
2743 fprintf(f
, "%02X ",(int)buf
[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)
2757 n
= per_line
- (i
%per_line
);
2759 if (n
>(per_line
/2)) 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
);
2773 void print_asc(int level
, unsigned char *buf
,int len
)
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
;
2786 DEBUG(level
,("[%03X] ",i
));
2788 DEBUG(level
,("%02X ",(int)buf
[i
]));
2790 if (i
%8 == 0) DEBUG(level
,(" "));
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
));
2802 if (n
>8) DEBUG(level
,(" "));
2803 while (n
--) DEBUG(level
,(" "));
2806 print_asc(level
,&buf
[i
-(i
%16)],n
); DEBUG(level
,(" "));
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
)
2831 res
^= (c
<< (i
% 15)) ^ (c
>> (15-(i
%15)));
2836 } /* str_checksum */
2841 /*****************************************************************
2842 zero a memory area then free it. Used to catch bugs faster
2843 *****************************************************************/
2844 void zero_free(void *p
, size_t size
)
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))
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",
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
) ));
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",
2889 return saved_current_limit
;
2892 #if defined(RLIM_INFINITY)
2893 if(rlp
.rlim_cur
== RLIM_INFINITY
)
2894 return saved_current_limit
;
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
;