* samba/lib/util.c (tmpdir): Use MC_TMPDIR environment variable.
[midnight-commander.git] / vfs / samba / lib / util.c
blob2e165dffc9ae9b0cc3cb0ec15718ea990ea184e0
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 Samba utility functions
5 Copyright (C) Andrew Tridgell 1992-1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "includes.h"
24 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
25 #ifdef WITH_NISPLUS_HOME
26 #ifdef BROKEN_NISPLUS_INCLUDE_FILES
28 * The following lines are needed due to buggy include files
29 * in Solaris 2.6 which define GROUP in both /usr/include/sys/acl.h and
30 * also in /usr/include/rpcsvc/nis.h. The definitions conflict. JRA.
31 * Also GROUP_OBJ is defined as 0x4 in /usr/include/sys/acl.h and as
32 * an enum in /usr/include/rpcsvc/nis.h.
35 #if defined(GROUP)
36 #undef GROUP
37 #endif
39 #if defined(GROUP_OBJ)
40 #undef GROUP_OBJ
41 #endif
43 #endif /* BROKEN_NISPLUS_INCLUDE_FILES */
45 #include <rpcsvc/nis.h>
47 #else /* !WITH_NISPLUS_HOME */
49 #include "rpcsvc/ypclnt.h"
51 #endif /* WITH_NISPLUS_HOME */
52 #endif /* HAVE_NETGROUP && WITH_AUTOMOUNT */
54 #ifdef WITH_SSL
55 #include <ssl.h>
56 #undef Realloc /* SSLeay defines this and samba has a function of this name */
57 extern SSL *ssl;
58 extern int sslFd;
59 #endif /* WITH_SSL */
61 extern int DEBUGLEVEL;
63 int Protocol = PROTOCOL_COREPLUS;
65 /* a default finfo structure to ensure all fields are sensible */
66 file_info def_finfo = {-1,0,0,0,0,0,0,""};
68 /* the client file descriptor */
69 extern int Client;
71 /* this is used by the chaining code */
72 int chain_size = 0;
74 int trans_num = 0;
77 case handling on filenames
79 int case_default = CASE_LOWER;
81 /* the following control case operations - they are put here so the
82 client can link easily */
83 BOOL case_sensitive;
84 BOOL case_preserve;
85 BOOL use_mangled_map = False;
86 BOOL short_case_preserve;
87 BOOL case_mangle;
89 fstring remote_machine="";
90 fstring local_machine="";
91 fstring remote_arch="UNKNOWN";
92 static enum remote_arch_types ra_type = RA_UNKNOWN;
93 fstring remote_proto="UNKNOWN";
94 pstring myhostname="";
95 pstring user_socket_options="";
97 pstring sesssetup_user="";
98 pstring samlogon_user="";
100 BOOL sam_logon_in_ssb = False;
102 pstring global_myname = "";
103 fstring global_myworkgroup = "";
104 char **my_netbios_names;
106 static char *filename_dos(char *path,char *buf);
110 /****************************************************************************
111 find a suitable temporary directory. The result should be copied immediately
112 as it may be overwritten by a subsequent call
113 ****************************************************************************/
114 char *tmpdir(void)
116 char *p;
117 if ((p = getenv("MC_TMPDIR")) || (p = getenv("TMPDIR"))) {
118 return p;
120 return "/tmp";
123 /****************************************************************************
124 determine whether we are in the specified group
125 ****************************************************************************/
127 BOOL in_group(gid_t group, gid_t current_gid, int ngroups, gid_t *groups)
129 int i;
131 if (group == current_gid) return(True);
133 for (i=0;i<ngroups;i++)
134 if (group == groups[i])
135 return(True);
137 return(False);
141 /****************************************************************************
142 like atoi but gets the value up to the separater character
143 ****************************************************************************/
144 char *Atoic(char *p, int *n, char *c)
146 if (!isdigit((int)*p))
148 DEBUG(5, ("Atoic: malformed number\n"));
149 return NULL;
152 (*n) = atoi(p);
154 while ((*p) && isdigit((int)*p))
156 p++;
159 if (strchr(c, *p) == NULL)
161 DEBUG(5, ("Atoic: no separator characters (%s) not found\n", c));
162 return NULL;
165 return p;
168 /*************************************************************************
169 reads a list of numbers
170 *************************************************************************/
171 char *get_numlist(char *p, uint32 **num, int *count)
173 int val;
175 if (num == NULL || count == NULL)
177 return NULL;
180 (*count) = 0;
181 (*num ) = NULL;
183 while ((p = Atoic(p, &val, ":,")) != NULL && (*p) != ':')
185 (*num) = Realloc((*num), ((*count)+1) * sizeof(uint32));
186 if ((*num) == NULL)
188 return NULL;
190 (*num)[(*count)] = val;
191 (*count)++;
192 p++;
195 return p;
198 /*******************************************************************
199 copy an IP address from one buffer to another
200 ********************************************************************/
201 void putip(void *dest,void *src)
203 memcpy(dest,src,4);
207 #define TRUNCATE_NETBIOS_NAME 1
209 /*******************************************************************
210 convert, possibly using a stupid microsoft-ism which has destroyed
211 the transport independence of netbios (for CIFS vendors that usually
212 use the Win95-type methods, not for NT to NT communication, which uses
213 DCE/RPC and therefore full-length unicode strings...) a dns name into
214 a netbios name.
216 the netbios name (NOT necessarily null-terminated) is truncated to 15
217 characters.
219 ******************************************************************/
220 char *dns_to_netbios_name(char *dns_name)
222 static char netbios_name[16];
223 int i;
224 StrnCpy(netbios_name, dns_name, 15);
225 netbios_name[15] = 0;
227 #ifdef TRUNCATE_NETBIOS_NAME
228 /* ok. this is because of a stupid microsoft-ism. if the called host
229 name contains a '.', microsoft clients expect you to truncate the
230 netbios name up to and including the '.' this even applies, by
231 mistake, to workgroup (domain) names, which is _really_ daft.
233 for (i = 15; i >= 0; i--)
235 if (netbios_name[i] == '.')
237 netbios_name[i] = 0;
238 break;
241 #endif /* TRUNCATE_NETBIOS_NAME */
243 return netbios_name;
247 /****************************************************************************
248 interpret the weird netbios "name". Return the name type
249 ****************************************************************************/
250 static int name_interpret(char *in,char *out)
252 int ret;
253 int len = (*in++) / 2;
255 *out=0;
257 if (len > 30 || len<1) return(0);
259 while (len--)
261 if (in[0] < 'A' || in[0] > 'P' || in[1] < 'A' || in[1] > 'P') {
262 *out = 0;
263 return(0);
265 *out = ((in[0]-'A')<<4) + (in[1]-'A');
266 in += 2;
267 out++;
269 *out = 0;
270 ret = out[-1];
272 #ifdef NETBIOS_SCOPE
273 /* Handle any scope names */
274 while(*in)
276 *out++ = '.'; /* Scope names are separated by periods */
277 len = *(unsigned char *)in++;
278 StrnCpy(out, in, len);
279 out += len;
280 *out=0;
281 in += len;
283 #endif
284 return(ret);
287 /****************************************************************************
288 mangle a name into netbios format
290 Note: <Out> must be (33 + strlen(scope) + 2) bytes long, at minimum.
291 ****************************************************************************/
292 int name_mangle( char *In, char *Out, char name_type )
294 int i;
295 int c;
296 int len;
297 char buf[20];
298 char *p = Out;
299 extern pstring global_scope;
301 /* Safely copy the input string, In, into buf[]. */
302 (void)memset( buf, 0, 20 );
303 if (strcmp(In,"*") == 0)
304 buf[0] = '*';
305 else
306 (void)slprintf( buf, sizeof(buf) - 1, "%-15.15s%c", In, name_type );
308 /* Place the length of the first field into the output buffer. */
309 p[0] = 32;
310 p++;
312 /* Now convert the name to the rfc1001/1002 format. */
313 for( i = 0; i < 16; i++ )
315 c = toupper( buf[i] );
316 p[i*2] = ( (c >> 4) & 0x000F ) + 'A';
317 p[(i*2)+1] = (c & 0x000F) + 'A';
319 p += 32;
320 p[0] = '\0';
322 /* Add the scope string. */
323 for( i = 0, len = 0; NULL != global_scope; i++, len++ )
325 switch( global_scope[i] )
327 case '\0':
328 p[0] = len;
329 if( len > 0 )
330 p[len+1] = 0;
331 return( name_len(Out) );
332 case '.':
333 p[0] = len;
334 p += (len + 1);
335 len = -1;
336 break;
337 default:
338 p[len+1] = global_scope[i];
339 break;
343 return( name_len(Out) );
344 } /* name_mangle */
346 /*******************************************************************
347 check if a file exists
348 ********************************************************************/
349 BOOL file_exist(char *fname,SMB_STRUCT_STAT *sbuf)
351 SMB_STRUCT_STAT st;
352 if (!sbuf) sbuf = &st;
354 if (sys_stat(fname,sbuf) != 0)
355 return(False);
357 return(S_ISREG(sbuf->st_mode));
360 /*******************************************************************
361 check a files mod time
362 ********************************************************************/
363 time_t file_modtime(char *fname)
365 SMB_STRUCT_STAT st;
367 if (sys_stat(fname,&st) != 0)
368 return(0);
370 return(st.st_mtime);
373 /*******************************************************************
374 check if a directory exists
375 ********************************************************************/
376 BOOL directory_exist(char *dname,SMB_STRUCT_STAT *st)
378 SMB_STRUCT_STAT st2;
379 BOOL ret;
381 if (!st) st = &st2;
383 if (sys_stat(dname,st) != 0)
384 return(False);
386 ret = S_ISDIR(st->st_mode);
387 if(!ret)
388 errno = ENOTDIR;
389 return ret;
392 /*******************************************************************
393 returns the size in bytes of the named file
394 ********************************************************************/
395 SMB_OFF_T file_size(char *file_name)
397 SMB_STRUCT_STAT buf;
398 buf.st_size = 0;
399 if(sys_stat(file_name,&buf) != 0)
400 return (SMB_OFF_T)-1;
401 return(buf.st_size);
404 /*******************************************************************
405 return a string representing an attribute for a file
406 ********************************************************************/
407 char *attrib_string(uint16 mode)
409 static fstring attrstr;
411 attrstr[0] = 0;
413 if (mode & aVOLID) fstrcat(attrstr,"V");
414 if (mode & aDIR) fstrcat(attrstr,"D");
415 if (mode & aARCH) fstrcat(attrstr,"A");
416 if (mode & aHIDDEN) fstrcat(attrstr,"H");
417 if (mode & aSYSTEM) fstrcat(attrstr,"S");
418 if (mode & aRONLY) fstrcat(attrstr,"R");
420 return(attrstr);
425 /****************************************************************************
426 make a file into unix format
427 ****************************************************************************/
428 void unix_format(char *fname)
430 string_replace(fname,'\\','/');
433 /****************************************************************************
434 make a file into dos format
435 ****************************************************************************/
436 void dos_format(char *fname)
438 string_replace(fname,'/','\\');
441 /*******************************************************************
442 show a smb message structure
443 ********************************************************************/
444 void show_msg(char *buf)
446 int i;
447 int bcc=0;
449 if (DEBUGLEVEL < 5) return;
451 DEBUG(5,("size=%d\nsmb_com=0x%x\nsmb_rcls=%d\nsmb_reh=%d\nsmb_err=%d\nsmb_flg=%d\nsmb_flg2=%d\n",
452 smb_len(buf),
453 (int)CVAL(buf,smb_com),
454 (int)CVAL(buf,smb_rcls),
455 (int)CVAL(buf,smb_reh),
456 (int)SVAL(buf,smb_err),
457 (int)CVAL(buf,smb_flg),
458 (int)SVAL(buf,smb_flg2)));
459 DEBUG(5,("smb_tid=%d\nsmb_pid=%d\nsmb_uid=%d\nsmb_mid=%d\nsmt_wct=%d\n",
460 (int)SVAL(buf,smb_tid),
461 (int)SVAL(buf,smb_pid),
462 (int)SVAL(buf,smb_uid),
463 (int)SVAL(buf,smb_mid),
464 (int)CVAL(buf,smb_wct)));
466 for (i=0;i<(int)CVAL(buf,smb_wct);i++)
468 DEBUG(5,("smb_vwv[%d]=%d (0x%X)\n",i,
469 SVAL(buf,smb_vwv+2*i),SVAL(buf,smb_vwv+2*i)));
472 bcc = (int)SVAL(buf,smb_vwv+2*(CVAL(buf,smb_wct)));
474 DEBUG(5,("smb_bcc=%d\n",bcc));
476 if (DEBUGLEVEL < 10) return;
478 if (DEBUGLEVEL < 50)
480 bcc = MIN(bcc, 512);
483 dump_data(10, smb_buf(buf), bcc);
485 /*******************************************************************
486 return the length of an smb packet
487 ********************************************************************/
488 int smb_len(char *buf)
490 return( PVAL(buf,3) | (PVAL(buf,2)<<8) | ((PVAL(buf,1)&1)<<16) );
493 /*******************************************************************
494 set the length of an smb packet
495 ********************************************************************/
496 void _smb_setlen(char *buf,int len)
498 buf[0] = 0;
499 buf[1] = (len&0x10000)>>16;
500 buf[2] = (len&0xFF00)>>8;
501 buf[3] = len&0xFF;
504 /*******************************************************************
505 set the length and marker of an smb packet
506 ********************************************************************/
507 void smb_setlen(char *buf,int len)
509 _smb_setlen(buf,len);
511 CVAL(buf,4) = 0xFF;
512 CVAL(buf,5) = 'S';
513 CVAL(buf,6) = 'M';
514 CVAL(buf,7) = 'B';
517 /*******************************************************************
518 setup the word count and byte count for a smb message
519 ********************************************************************/
520 int set_message(char *buf,int num_words,int num_bytes,BOOL zero)
522 if (zero)
523 memset(buf + smb_size,'\0',num_words*2 + num_bytes);
524 CVAL(buf,smb_wct) = num_words;
525 SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
526 smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
527 return (smb_size + num_words*2 + num_bytes);
530 /*******************************************************************
531 return the number of smb words
532 ********************************************************************/
533 static int smb_numwords(char *buf)
535 return (CVAL(buf,smb_wct));
538 /*******************************************************************
539 return the size of the smb_buf region of a message
540 ********************************************************************/
541 int smb_buflen(char *buf)
543 return(SVAL(buf,smb_vwv0 + smb_numwords(buf)*2));
546 /*******************************************************************
547 return a pointer to the smb_buf data area
548 ********************************************************************/
549 static int smb_buf_ofs(char *buf)
551 return (smb_size + CVAL(buf,smb_wct)*2);
554 /*******************************************************************
555 return a pointer to the smb_buf data area
556 ********************************************************************/
557 char *smb_buf(char *buf)
559 return (buf + smb_buf_ofs(buf));
562 /*******************************************************************
563 return the SMB offset into an SMB buffer
564 ********************************************************************/
565 int smb_offset(char *p,char *buf)
567 return(PTR_DIFF(p,buf+4) + chain_size);
570 /*******************************************************************
571 reduce a file name, removing .. elements.
572 ********************************************************************/
573 void dos_clean_name(char *s)
575 char *p=NULL;
577 DEBUG(3,("dos_clean_name [%s]\n",s));
579 /* remove any double slashes */
580 string_sub(s, "\\\\", "\\");
582 while ((p = strstr(s,"\\..\\")) != NULL)
584 pstring s1;
586 *p = 0;
587 pstrcpy(s1,p+3);
589 if ((p=strrchr(s,'\\')) != NULL)
590 *p = 0;
591 else
592 *s = 0;
593 pstrcat(s,s1);
596 trim_string(s,NULL,"\\..");
598 string_sub(s, "\\.\\", "\\");
601 /*******************************************************************
602 reduce a file name, removing .. elements.
603 ********************************************************************/
604 void unix_clean_name(char *s)
606 char *p=NULL;
608 DEBUG(3,("unix_clean_name [%s]\n",s));
610 /* remove any double slashes */
611 string_sub(s, "//","/");
613 /* Remove leading ./ characters */
614 if(strncmp(s, "./", 2) == 0) {
615 trim_string(s, "./", NULL);
616 if(*s == 0)
617 pstrcpy(s,"./");
620 while ((p = strstr(s,"/../")) != NULL)
622 pstring s1;
624 *p = 0;
625 pstrcpy(s1,p+3);
627 if ((p=strrchr(s,'/')) != NULL)
628 *p = 0;
629 else
630 *s = 0;
631 pstrcat(s,s1);
634 trim_string(s,NULL,"/..");
637 /*******************************************************************
638 reduce a file name, removing .. elements and checking that
639 it is below dir in the heirachy. This uses dos_GetWd() and so must be run
640 on the system that has the referenced file system.
642 widelinks are allowed if widelinks is true
643 ********************************************************************/
644 #if 0
645 BOOL reduce_name(char *s,char *dir,BOOL widelinks)
647 #ifndef REDUCE_PATHS
648 return True;
649 #else
650 pstring dir2;
651 pstring wd;
652 pstring base_name;
653 pstring newname;
654 char *p=NULL;
655 BOOL relative = (*s != '/');
657 *dir2 = *wd = *base_name = *newname = 0;
659 if (widelinks)
661 unix_clean_name(s);
662 /* can't have a leading .. */
663 if (strncmp(s,"..",2) == 0 && (s[2]==0 || s[2]=='/'))
665 DEBUG(3,("Illegal file name? (%s)\n",s));
666 return(False);
669 if (strlen(s) == 0)
670 pstrcpy(s,"./");
672 return(True);
675 DEBUG(3,("reduce_name [%s] [%s]\n",s,dir));
677 /* remove any double slashes */
678 string_sub(s,"//","/");
680 pstrcpy(base_name,s);
681 p = strrchr(base_name,'/');
683 if (!p)
684 return(True);
686 if (!dos_GetWd(wd))
688 DEBUG(0,("couldn't getwd for %s %s\n",s,dir));
689 return(False);
692 if (dos_ChDir(dir) != 0)
694 DEBUG(0,("couldn't chdir to %s\n",dir));
695 return(False);
698 if (!dos_GetWd(dir2))
700 DEBUG(0,("couldn't getwd for %s\n",dir));
701 dos_ChDir(wd);
702 return(False);
705 if (p && (p != base_name))
707 *p = 0;
708 if (strcmp(p+1,".")==0)
709 p[1]=0;
710 if (strcmp(p+1,"..")==0)
711 *p = '/';
714 if (dos_ChDir(base_name) != 0)
716 dos_ChDir(wd);
717 DEBUG(3,("couldn't chdir for %s %s basename=%s\n",s,dir,base_name));
718 return(False);
721 if (!dos_GetWd(newname))
723 dos_ChDir(wd);
724 DEBUG(2,("couldn't get wd for %s %s\n",s,dir2));
725 return(False);
728 if (p && (p != base_name))
730 pstrcat(newname,"/");
731 pstrcat(newname,p+1);
735 size_t l = strlen(dir2);
736 if (dir2[l-1] == '/')
737 l--;
739 if (strncmp(newname,dir2,l) != 0)
741 dos_ChDir(wd);
742 DEBUG(2,("Bad access attempt? s=%s dir=%s newname=%s l=%d\n",s,dir2,newname,(int)l));
743 return(False);
746 if (relative)
748 if (newname[l] == '/')
749 pstrcpy(s,newname + l + 1);
750 else
751 pstrcpy(s,newname+l);
753 else
754 pstrcpy(s,newname);
757 dos_ChDir(wd);
759 if (strlen(s) == 0)
760 pstrcpy(s,"./");
762 DEBUG(3,("reduced to %s\n",s));
763 return(True);
764 #endif
766 #endif /* 0 */
767 /****************************************************************************
768 expand some *s
769 ****************************************************************************/
770 static void expand_one(char *Mask,int len)
772 char *p1;
773 while ((p1 = strchr(Mask,'*')) != NULL)
775 int lfill = (len+1) - strlen(Mask);
776 int l1= (p1 - Mask);
777 pstring tmp;
778 pstrcpy(tmp,Mask);
779 memset(tmp+l1,'?',lfill);
780 pstrcpy(tmp + l1 + lfill,Mask + l1 + 1);
781 pstrcpy(Mask,tmp);
785 /****************************************************************************
786 parse out a directory name from a path name. Assumes dos style filenames.
787 ****************************************************************************/
788 static void dirname_dos(char *path,char *buf)
790 split_at_last_component(path, buf, '\\', NULL);
794 /****************************************************************************
795 expand a wildcard expression, replacing *s with ?s
796 ****************************************************************************/
797 void expand_mask(char *Mask,BOOL doext)
799 pstring mbeg,mext;
800 pstring dirpart;
801 pstring filepart;
802 BOOL hasdot = False;
803 char *p1;
804 BOOL absolute = (*Mask == '\\');
806 *mbeg = *mext = *dirpart = *filepart = 0;
808 /* parse the directory and filename */
809 if (strchr(Mask,'\\'))
810 dirname_dos(Mask,dirpart);
812 filename_dos(Mask,filepart);
814 pstrcpy(mbeg,filepart);
815 if ((p1 = strchr(mbeg,'.')) != NULL)
817 hasdot = True;
818 *p1 = 0;
819 p1++;
820 pstrcpy(mext,p1);
822 else
824 pstrcpy(mext,"");
825 if (strlen(mbeg) > 8)
827 pstrcpy(mext,mbeg + 8);
828 mbeg[8] = 0;
832 if (*mbeg == 0)
833 pstrcpy(mbeg,"????????");
834 if ((*mext == 0) && doext && !hasdot)
835 pstrcpy(mext,"???");
837 if (strequal(mbeg,"*") && *mext==0)
838 pstrcpy(mext,"*");
840 /* expand *'s */
841 expand_one(mbeg,8);
842 if (*mext)
843 expand_one(mext,3);
845 pstrcpy(Mask,dirpart);
846 if (*dirpart || absolute) pstrcat(Mask,"\\");
847 pstrcat(Mask,mbeg);
848 pstrcat(Mask,".");
849 pstrcat(Mask,mext);
851 DEBUG(6,("Mask expanded to [%s]\n",Mask));
856 /****************************************************************************
857 make a dir struct
858 ****************************************************************************/
859 void make_dir_struct(char *buf,char *mask,char *fname,SMB_OFF_T size,int mode,time_t date)
861 char *p;
862 pstring mask2;
864 pstrcpy(mask2,mask);
866 if ((mode & aDIR) != 0)
867 size = 0;
869 memset(buf+1,' ',11);
870 if ((p = strchr(mask2,'.')) != NULL)
872 *p = 0;
873 memcpy(buf+1,mask2,MIN(strlen(mask2),8));
874 memcpy(buf+9,p+1,MIN(strlen(p+1),3));
875 *p = '.';
877 else
878 memcpy(buf+1,mask2,MIN(strlen(mask2),11));
880 memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
881 CVAL(buf,21) = mode;
882 put_dos_date(buf,22,date);
883 SSVAL(buf,26,size & 0xFFFF);
884 SSVAL(buf,28,(size >> 16)&0xFFFF);
885 StrnCpy(buf+30,fname,12);
886 if (!case_sensitive)
887 strupper(buf+30);
888 DEBUG(8,("put name [%s] into dir struct\n",buf+30));
892 /*******************************************************************
893 close the low 3 fd's and open dev/null in their place
894 ********************************************************************/
895 void close_low_fds(void)
897 int fd;
898 int i;
899 close(0); close(1); close(2);
900 /* try and use up these file descriptors, so silly
901 library routines writing to stdout etc won't cause havoc */
902 for (i=0;i<3;i++) {
903 fd = sys_open("/dev/null",O_RDWR,0);
904 if (fd < 0) fd = sys_open("/dev/null",O_WRONLY,0);
905 if (fd < 0) {
906 DEBUG(0,("Cannot open /dev/null\n"));
907 return;
909 if (fd != i) {
910 DEBUG(0,("Didn't get file descriptor %d\n",i));
911 return;
916 /****************************************************************************
917 Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
918 else
919 if SYSV use O_NDELAY
920 if BSD use FNDELAY
921 ****************************************************************************/
922 int set_blocking(int fd, BOOL set)
924 int val;
925 #ifdef O_NONBLOCK
926 #define FLAG_TO_SET O_NONBLOCK
927 #else
928 #ifdef SYSV
929 #define FLAG_TO_SET O_NDELAY
930 #else /* BSD */
931 #define FLAG_TO_SET FNDELAY
932 #endif
933 #endif
935 if((val = fcntl(fd, F_GETFL, 0)) == -1)
936 return -1;
937 if(set) /* Turn blocking on - ie. clear nonblock flag */
938 val &= ~FLAG_TO_SET;
939 else
940 val |= FLAG_TO_SET;
941 return fcntl( fd, F_SETFL, val);
942 #undef FLAG_TO_SET
946 /*******************************************************************
947 find the difference in milliseconds between two struct timeval
948 values
949 ********************************************************************/
950 int TvalDiff(struct timeval *tvalold,struct timeval *tvalnew)
952 return((tvalnew->tv_sec - tvalold->tv_sec)*1000 +
953 ((int)tvalnew->tv_usec - (int)tvalold->tv_usec)/1000);
957 #if 0
958 /****************************************************************************
959 transfer some data between two fd's
960 ****************************************************************************/
961 SMB_OFF_T transfer_file(int infd,int outfd,SMB_OFF_T n,char *header,int headlen,int align)
963 static char *buf=NULL;
964 static int size=0;
965 char *buf1,*abuf;
966 SMB_OFF_T total = 0;
968 DEBUG(4,("transfer_file n=%.0f (head=%d) called\n",(double)n,headlen));
970 if (size == 0) {
971 size = lp_readsize();
972 size = MAX(size,1024);
975 while (!buf && size>0) {
976 buf = (char *)Realloc(buf,size+8);
977 if (!buf) size /= 2;
980 if (!buf) {
981 DEBUG(0,("Cannot allocate transfer buffer!\n"));
982 exit(1);
985 abuf = buf + (align%8);
987 if (header)
988 n += headlen;
990 while (n > 0)
992 int s = (int)MIN(n,(SMB_OFF_T)size);
993 int ret,ret2=0;
995 ret = 0;
997 if (header && (headlen >= MIN(s,1024))) {
998 buf1 = header;
999 s = headlen;
1000 ret = headlen;
1001 headlen = 0;
1002 header = NULL;
1003 } else {
1004 buf1 = abuf;
1007 if (header && headlen > 0)
1009 ret = MIN(headlen,size);
1010 memcpy(buf1,header,ret);
1011 headlen -= ret;
1012 header += ret;
1013 if (headlen <= 0) header = NULL;
1016 if (s > ret)
1017 ret += read(infd,buf1+ret,s-ret);
1019 if (ret > 0)
1021 ret2 = (outfd>=0?write_data(outfd,buf1,ret):ret);
1022 if (ret2 > 0) total += ret2;
1023 /* if we can't write then dump excess data */
1024 if (ret2 != ret)
1025 transfer_file(infd,-1,n-(ret+headlen),NULL,0,0);
1027 if (ret <= 0 || ret2 != ret)
1028 return(total);
1029 n -= ret;
1031 return(total);
1033 #endif /* 0 */
1036 /****************************************************************************
1037 find a pointer to a netbios name
1038 ****************************************************************************/
1039 static char *name_ptr(char *buf,int ofs)
1041 unsigned char c = *(unsigned char *)(buf+ofs);
1043 if ((c & 0xC0) == 0xC0)
1045 uint16 l;
1046 char p[2];
1047 memcpy(p,buf+ofs,2);
1048 p[0] &= ~0xC0;
1049 l = RSVAL(p,0);
1050 DEBUG(5,("name ptr to pos %d from %d is %s\n",l,ofs,buf+l));
1051 return(buf + l);
1053 else
1054 return(buf+ofs);
1057 /****************************************************************************
1058 extract a netbios name from a buf
1059 ****************************************************************************/
1060 int name_extract(char *buf,int ofs,char *name)
1062 char *p = name_ptr(buf,ofs);
1063 int d = PTR_DIFF(p,buf+ofs);
1064 pstrcpy(name,"");
1065 if (d < -50 || d > 50) return(0);
1066 return(name_interpret(p,name));
1069 /****************************************************************************
1070 return the total storage length of a mangled name
1071 ****************************************************************************/
1072 int name_len(char *s1)
1074 /* NOTE: this argument _must_ be unsigned */
1075 unsigned char *s = (unsigned char *)s1;
1076 int len;
1078 /* If the two high bits of the byte are set, return 2. */
1079 if (0xC0 == (*s & 0xC0))
1080 return(2);
1082 /* Add up the length bytes. */
1083 for (len = 1; (*s); s += (*s) + 1) {
1084 len += *s + 1;
1085 SMB_ASSERT(len < 80);
1088 return(len);
1089 } /* name_len */
1092 /*******************************************************************
1093 sleep for a specified number of milliseconds
1094 ********************************************************************/
1095 void msleep(int t)
1097 int tdiff=0;
1098 struct timeval tval,t1,t2;
1099 fd_set fds;
1101 GetTimeOfDay(&t1);
1102 GetTimeOfDay(&t2);
1104 while (tdiff < t) {
1105 tval.tv_sec = (t-tdiff)/1000;
1106 tval.tv_usec = 1000*((t-tdiff)%1000);
1108 FD_ZERO(&fds);
1109 errno = 0;
1110 sys_select(0,&fds,&tval);
1112 GetTimeOfDay(&t2);
1113 tdiff = TvalDiff(&t1,&t2);
1118 /*********************************************************
1119 * Recursive routine that is called by unix_mask_match.
1120 * Does the actual matching. This is the 'original code'
1121 * used by the unix matcher.
1122 *********************************************************/
1123 static BOOL unix_do_match(char *str, char *regexp, int case_sig)
1125 char *p;
1127 for( p = regexp; *p && *str; ) {
1128 switch(*p) {
1129 case '?':
1130 str++; p++;
1131 break;
1133 case '*':
1134 /* Look for a character matching
1135 the one after the '*' */
1136 p++;
1137 if(!*p)
1138 return True; /* Automatic match */
1139 while(*str) {
1140 while(*str && (case_sig ? (*p != *str) : (toupper(*p)!=toupper(*str))))
1141 str++;
1142 if(unix_do_match(str,p,case_sig))
1143 return True;
1144 if(!*str)
1145 return False;
1146 else
1147 str++;
1149 return False;
1151 default:
1152 if(case_sig) {
1153 if(*str != *p)
1154 return False;
1155 } else {
1156 if(toupper(*str) != toupper(*p))
1157 return False;
1159 str++, p++;
1160 break;
1163 if(!*p && !*str)
1164 return True;
1166 if (!*p && str[0] == '.' && str[1] == 0)
1167 return(True);
1169 if (!*str && *p == '?')
1171 while (*p == '?') p++;
1172 return(!*p);
1175 if(!*str && (*p == '*' && p[1] == '\0'))
1176 return True;
1177 return False;
1181 /*********************************************************
1182 * Routine to match a given string with a regexp - uses
1183 * simplified regexp that takes * and ? only. Case can be
1184 * significant or not.
1185 * This is the 'original code' used by the unix matcher.
1186 *********************************************************/
1188 static BOOL unix_mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
1190 char *p;
1191 pstring p1, p2;
1192 fstring ebase,eext,sbase,sext;
1194 BOOL matched;
1196 /* Make local copies of str and regexp */
1197 StrnCpy(p1,regexp,sizeof(pstring)-1);
1198 StrnCpy(p2,str,sizeof(pstring)-1);
1200 if (!strchr(p2,'.')) {
1201 pstrcat(p2,".");
1204 /* Remove any *? and ** as they are meaningless */
1205 for(p = p1; *p; p++)
1206 while( *p == '*' && (p[1] == '?' ||p[1] == '*'))
1207 (void)pstrcpy( &p[1], &p[2]);
1209 if (strequal(p1,"*")) return(True);
1211 DEBUG(8,("unix_mask_match str=<%s> regexp=<%s>, case_sig = %d\n", p2, p1, case_sig));
1213 if (trans2) {
1214 fstrcpy(ebase,p1);
1215 fstrcpy(sbase,p2);
1216 } else {
1217 if ((p=strrchr(p1,'.'))) {
1218 *p = 0;
1219 fstrcpy(ebase,p1);
1220 fstrcpy(eext,p+1);
1221 } else {
1222 fstrcpy(ebase,p1);
1223 eext[0] = 0;
1226 if (!strequal(p2,".") && !strequal(p2,"..") && (p=strrchr(p2,'.'))) {
1227 *p = 0;
1228 fstrcpy(sbase,p2);
1229 fstrcpy(sext,p+1);
1230 } else {
1231 fstrcpy(sbase,p2);
1232 fstrcpy(sext,"");
1236 matched = unix_do_match(sbase,ebase,case_sig) &&
1237 (trans2 || unix_do_match(sext,eext,case_sig));
1239 DEBUG(8,("unix_mask_match returning %d\n", matched));
1241 return matched;
1244 /*********************************************************
1245 * Recursive routine that is called by mask_match.
1246 * Does the actual matching. Returns True if matched,
1247 * False if failed. This is the 'new' NT style matcher.
1248 *********************************************************/
1250 BOOL do_match(char *str, char *regexp, int case_sig)
1252 char *p;
1254 for( p = regexp; *p && *str; ) {
1255 switch(*p) {
1256 case '?':
1257 str++; p++;
1258 break;
1260 case '*':
1261 /* Look for a character matching
1262 the one after the '*' */
1263 p++;
1264 if(!*p)
1265 return True; /* Automatic match */
1266 while(*str) {
1267 while(*str && (case_sig ? (*p != *str) : (toupper(*p)!=toupper(*str))))
1268 str++;
1269 /* Now eat all characters that match, as
1270 we want the *last* character to match. */
1271 while(*str && (case_sig ? (*p == *str) : (toupper(*p)==toupper(*str))))
1272 str++;
1273 str--; /* We've eaten the match char after the '*' */
1274 if(do_match(str,p,case_sig)) {
1275 return True;
1277 if(!*str) {
1278 return False;
1279 } else {
1280 str++;
1283 return False;
1285 default:
1286 if(case_sig) {
1287 if(*str != *p) {
1288 return False;
1290 } else {
1291 if(toupper(*str) != toupper(*p)) {
1292 return False;
1295 str++, p++;
1296 break;
1300 if(!*p && !*str)
1301 return True;
1303 if (!*p && str[0] == '.' && str[1] == 0) {
1304 return(True);
1307 if (!*str && *p == '?') {
1308 while (*p == '?')
1309 p++;
1310 return(!*p);
1313 if(!*str && (*p == '*' && p[1] == '\0')) {
1314 return True;
1317 return False;
1321 /*********************************************************
1322 * Routine to match a given string with a regexp - uses
1323 * simplified regexp that takes * and ? only. Case can be
1324 * significant or not.
1325 * The 8.3 handling was rewritten by Ums Harald <Harald.Ums@pro-sieben.de>
1326 * This is the new 'NT style' matcher.
1327 *********************************************************/
1329 BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
1331 char *p;
1332 pstring t_pattern, t_filename, te_pattern, te_filename;
1333 fstring ebase,eext,sbase,sext;
1335 BOOL matched = False;
1337 /* Make local copies of str and regexp */
1338 pstrcpy(t_pattern,regexp);
1339 pstrcpy(t_filename,str);
1341 if(trans2) {
1343 /* a special case for 16 bit apps */
1344 if (strequal(t_pattern,"????????.???"))
1345 pstrcpy(t_pattern,"*");
1347 #if 0
1349 * Handle broken clients that send us old 8.3 format.
1351 string_sub(t_pattern,"????????","*");
1352 string_sub(t_pattern,".???",".*");
1353 #endif
1356 #if 0
1358 * Not sure if this is a good idea. JRA.
1360 if(trans2 && is_8_3(t_pattern,False) && is_8_3(t_filename,False))
1361 trans2 = False;
1362 #endif
1364 #if 0
1365 if (!strchr(t_filename,'.')) {
1366 pstrcat(t_filename,".");
1368 #endif
1370 /* Remove any *? and ** as they are meaningless */
1371 string_sub(t_pattern, "*?", "*");
1372 string_sub(t_pattern, "**", "*");
1374 if (strequal(t_pattern,"*"))
1375 return(True);
1377 DEBUG(8,("mask_match str=<%s> regexp=<%s>, case_sig = %d\n", t_filename, t_pattern, case_sig));
1379 if(trans2) {
1381 * Match each component of the regexp, split up by '.'
1382 * characters.
1384 char *fp, *rp, *cp2, *cp1;
1385 BOOL last_wcard_was_star = False;
1386 int num_path_components, num_regexp_components;
1388 pstrcpy(te_pattern,t_pattern);
1389 pstrcpy(te_filename,t_filename);
1391 * Remove multiple "*." patterns.
1393 string_sub(te_pattern, "*.*.", "*.");
1394 num_regexp_components = count_chars(te_pattern, '.');
1395 num_path_components = count_chars(te_filename, '.');
1398 * Check for special 'hack' case of "DIR a*z". - needs to match a.b.c...z
1400 if(num_regexp_components == 0)
1401 matched = do_match( te_filename, te_pattern, case_sig);
1402 else {
1403 for( cp1 = te_pattern, cp2 = te_filename; cp1;) {
1404 fp = strchr(cp2, '.');
1405 if(fp)
1406 *fp = '\0';
1407 rp = strchr(cp1, '.');
1408 if(rp)
1409 *rp = '\0';
1411 if(cp1[strlen(cp1)-1] == '*')
1412 last_wcard_was_star = True;
1413 else
1414 last_wcard_was_star = False;
1416 if(!do_match(cp2, cp1, case_sig))
1417 break;
1419 cp1 = rp ? rp + 1 : NULL;
1420 cp2 = fp ? fp + 1 : "";
1422 if(last_wcard_was_star || ((cp1 != NULL) && (*cp1 == '*'))) {
1423 /* Eat the extra path components. */
1424 int i;
1426 for(i = 0; i < num_path_components - num_regexp_components; i++) {
1427 fp = strchr(cp2, '.');
1428 if(fp)
1429 *fp = '\0';
1431 if((cp1 != NULL) && do_match( cp2, cp1, case_sig)) {
1432 cp2 = fp ? fp + 1 : "";
1433 break;
1435 cp2 = fp ? fp + 1 : "";
1437 num_path_components -= i;
1440 if(cp1 == NULL && ((*cp2 == '\0') || last_wcard_was_star))
1441 matched = True;
1443 } else {
1445 /* -------------------------------------------------
1446 * Behaviour of Win95
1447 * for 8.3 filenames and 8.3 Wildcards
1448 * -------------------------------------------------
1450 if (strequal (t_filename, ".")) {
1452 * Patterns: *.* *. ?. ? ????????.??? are valid.
1455 if(strequal(t_pattern, "*.*") || strequal(t_pattern, "*.") ||
1456 strequal(t_pattern, "????????.???") ||
1457 strequal(t_pattern, "?.") || strequal(t_pattern, "?"))
1458 matched = True;
1459 } else if (strequal (t_filename, "..")) {
1461 * Patterns: *.* *. ?. ? *.? ????????.??? are valid.
1464 if(strequal(t_pattern, "*.*") || strequal(t_pattern, "*.") ||
1465 strequal(t_pattern, "?.") || strequal(t_pattern, "?") ||
1466 strequal(t_pattern, "????????.???") ||
1467 strequal(t_pattern, "*.?") || strequal(t_pattern, "?.*"))
1468 matched = True;
1469 } else {
1471 if ((p = strrchr (t_pattern, '.'))) {
1473 * Wildcard has a suffix.
1475 *p = 0;
1476 fstrcpy (ebase, t_pattern);
1477 if (p[1]) {
1478 fstrcpy (eext, p + 1);
1479 } else {
1480 /* pattern ends in DOT: treat as if there is no DOT */
1481 *eext = 0;
1482 if (strequal (ebase, "*"))
1483 return (True);
1485 } else {
1487 * No suffix for wildcard.
1489 fstrcpy (ebase, t_pattern);
1490 eext[0] = 0;
1493 p = strrchr (t_filename, '.');
1494 if (p && (p[1] == 0) ) {
1496 * Filename has an extension of '.' only.
1498 *p = 0; /* nuke dot at end of string */
1499 p = 0; /* and treat it as if there is no extension */
1502 if (p) {
1504 * Filename has an extension.
1506 *p = 0;
1507 fstrcpy (sbase, t_filename);
1508 fstrcpy (sext, p + 1);
1509 if (*eext) {
1510 matched = do_match(sbase, ebase, case_sig)
1511 && do_match(sext, eext, case_sig);
1512 } else {
1513 /* pattern has no extension */
1514 /* Really: match complete filename with pattern ??? means exactly 3 chars */
1515 matched = do_match(str, ebase, case_sig);
1517 } else {
1519 * Filename has no extension.
1521 fstrcpy (sbase, t_filename);
1522 fstrcpy (sext, "");
1523 if (*eext) {
1524 /* pattern has extension */
1525 matched = do_match(sbase, ebase, case_sig)
1526 && do_match(sext, eext, case_sig);
1527 } else {
1528 matched = do_match(sbase, ebase, case_sig);
1529 #ifdef EMULATE_WEIRD_W95_MATCHING
1531 * Even Microsoft has some problems
1532 * Behaviour Win95 -> local disk
1533 * is different from Win95 -> smb drive from Nt 4.0
1534 * This branch would reflect the Win95 local disk behaviour
1536 if (!matched) {
1537 /* a? matches aa and a in w95 */
1538 fstrcat (sbase, ".");
1539 matched = do_match(sbase, ebase, case_sig);
1541 #endif
1547 DEBUG(8,("mask_match returning %d\n", matched));
1549 return matched;
1553 #if 0
1554 /****************************************************************************
1555 set the length of a file from a filedescriptor.
1556 Returns 0 on success, -1 on failure.
1557 ****************************************************************************/
1559 int set_filelen(int fd, SMB_OFF_T len)
1561 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1562 extend a file with ftruncate. Provide alternate implementation
1563 for this */
1565 #ifdef HAVE_FTRUNCATE_EXTEND
1566 return sys_ftruncate(fd, len);
1567 #else
1568 SMB_STRUCT_STAT st;
1569 char c = 0;
1570 SMB_OFF_T currpos = sys_lseek(fd, (SMB_OFF_T)0, SEEK_CUR);
1572 if(currpos == -1)
1573 return -1;
1574 /* Do an fstat to see if the file is longer than
1575 the requested size (call ftruncate),
1576 or shorter, in which case seek to len - 1 and write 1
1577 byte of zero */
1578 if(sys_fstat(fd, &st)<0)
1579 return -1;
1581 #ifdef S_ISFIFO
1582 if (S_ISFIFO(st.st_mode))
1583 return 0;
1584 #endif
1586 if(st.st_size == len)
1587 return 0;
1588 if(st.st_size > len)
1589 return sys_ftruncate(fd, len);
1591 if(sys_lseek(fd, len-1, SEEK_SET) != len -1)
1592 return -1;
1593 if(write(fd, &c, 1)!=1)
1594 return -1;
1595 /* Seek to where we were */
1596 if(sys_lseek(fd, currpos, SEEK_SET) != currpos)
1597 return -1;
1598 return 0;
1599 #endif
1603 #ifdef HPUX
1604 /****************************************************************************
1605 this is a version of setbuffer() for those machines that only have setvbuf
1606 ****************************************************************************/
1607 void setbuffer(FILE *f,char *buf,int bufsize)
1609 setvbuf(f,buf,_IOFBF,bufsize);
1611 #endif
1612 #endif /* 0 */
1614 /****************************************************************************
1615 parse out a filename from a path name. Assumes dos style filenames.
1616 ****************************************************************************/
1617 static char *filename_dos(char *path,char *buf)
1619 char *p = strrchr(path,'\\');
1621 if (!p)
1622 pstrcpy(buf,path);
1623 else
1624 pstrcpy(buf,p+1);
1626 return(buf);
1631 /****************************************************************************
1632 expand a pointer to be a particular size
1633 ****************************************************************************/
1634 void *Realloc(void *p,size_t size)
1636 void *ret=NULL;
1638 if (size == 0) {
1639 if (p) free(p);
1640 DEBUG(5,("Realloc asked for 0 bytes\n"));
1641 return NULL;
1644 if (!p)
1645 ret = (void *)malloc(size);
1646 else
1647 ret = (void *)realloc(p,size);
1649 #ifdef MEM_MAN
1651 extern FILE *dbf;
1652 smb_mem_write_info(ret, dbf);
1654 #endif
1656 if (!ret)
1657 DEBUG(0,("Memory allocation error: failed to expand to %d bytes\n",(int)size));
1659 return(ret);
1663 /****************************************************************************
1664 get my own name and IP
1665 ****************************************************************************/
1666 BOOL get_myname(char *my_name,struct in_addr *ip)
1668 struct hostent *hp;
1669 pstring hostname;
1671 *hostname = 0;
1673 /* get my host name */
1674 if (gethostname(hostname, sizeof(hostname)) == -1)
1676 DEBUG(0,("gethostname failed\n"));
1677 return False;
1680 /* Ensure null termination. */
1681 hostname[sizeof(hostname)-1] = '\0';
1683 /* get host info */
1684 if ((hp = Get_Hostbyname(hostname)) == 0)
1686 DEBUG(0,( "Get_Hostbyname: Unknown host %s\n",hostname));
1687 return False;
1690 if (my_name)
1692 /* split off any parts after an initial . */
1693 char *p = strchr(hostname,'.');
1694 if (p) *p = 0;
1696 fstrcpy(my_name,hostname);
1699 if (ip)
1700 putip((char *)ip,(char *)hp->h_addr);
1702 return(True);
1706 /****************************************************************************
1707 true if two IP addresses are equal
1708 ****************************************************************************/
1709 BOOL ip_equal(struct in_addr ip1,struct in_addr ip2)
1711 uint32 a1,a2;
1712 a1 = ntohl(ip1.s_addr);
1713 a2 = ntohl(ip2.s_addr);
1714 return(a1 == a2);
1718 /****************************************************************************
1719 interpret a protocol description string, with a default
1720 ****************************************************************************/
1721 int interpret_protocol(char *str,int def)
1723 if (strequal(str,"NT1"))
1724 return(PROTOCOL_NT1);
1725 if (strequal(str,"LANMAN2"))
1726 return(PROTOCOL_LANMAN2);
1727 if (strequal(str,"LANMAN1"))
1728 return(PROTOCOL_LANMAN1);
1729 if (strequal(str,"CORE"))
1730 return(PROTOCOL_CORE);
1731 if (strequal(str,"COREPLUS"))
1732 return(PROTOCOL_COREPLUS);
1733 if (strequal(str,"CORE+"))
1734 return(PROTOCOL_COREPLUS);
1736 DEBUG(0,("Unrecognised protocol level %s\n",str));
1738 return(def);
1742 /****************************************************************************
1743 interpret an internet address or name into an IP address in 4 byte form
1744 ****************************************************************************/
1745 uint32 interpret_addr(char *str)
1747 struct hostent *hp;
1748 uint32 res;
1749 int i;
1750 BOOL pure_address = True;
1752 if (strcmp(str,"0.0.0.0") == 0) return(0);
1753 if (strcmp(str,"255.255.255.255") == 0) return(0xFFFFFFFF);
1755 for (i=0; pure_address && str[i]; i++)
1756 if (!(isdigit((int)str[i]) || str[i] == '.'))
1757 pure_address = False;
1759 /* if it's in the form of an IP address then get the lib to interpret it */
1760 if (pure_address) {
1761 res = inet_addr(str);
1762 } else {
1763 /* otherwise assume it's a network name of some sort and use
1764 Get_Hostbyname */
1765 if ((hp = Get_Hostbyname(str)) == 0) {
1766 DEBUG(3,("Get_Hostbyname: Unknown host. %s\n",str));
1767 return 0;
1769 if(hp->h_addr == NULL) {
1770 DEBUG(3,("Get_Hostbyname: host address is invalid for host %s\n",str));
1771 return 0;
1773 putip((char *)&res,(char *)hp->h_addr);
1776 if (res == (uint32)-1) return(0);
1778 return(res);
1781 /*******************************************************************
1782 a convenient addition to interpret_addr()
1783 ******************************************************************/
1784 struct in_addr *interpret_addr2(char *str)
1786 static struct in_addr ret;
1787 uint32 a = interpret_addr(str);
1788 ret.s_addr = a;
1789 return(&ret);
1792 /*******************************************************************
1793 check if an IP is the 0.0.0.0
1794 ******************************************************************/
1795 BOOL zero_ip(struct in_addr ip)
1797 uint32 a;
1798 putip((char *)&a,(char *)&ip);
1799 return(a == 0);
1803 /*******************************************************************
1804 matchname - determine if host name matches IP address
1805 ******************************************************************/
1806 BOOL matchname(char *remotehost,struct in_addr addr)
1808 struct hostent *hp;
1809 int i;
1811 if ((hp = Get_Hostbyname(remotehost)) == 0) {
1812 DEBUG(0,("Get_Hostbyname(%s): lookup failure.\n", remotehost));
1813 return False;
1817 * Make sure that gethostbyname() returns the "correct" host name.
1818 * Unfortunately, gethostbyname("localhost") sometimes yields
1819 * "localhost.domain". Since the latter host name comes from the
1820 * local DNS, we just have to trust it (all bets are off if the local
1821 * DNS is perverted). We always check the address list, though.
1824 if (strcasecmp(remotehost, hp->h_name)
1825 && strcasecmp(remotehost, "localhost")) {
1826 DEBUG(0,("host name/name mismatch: %s != %s\n",
1827 remotehost, hp->h_name));
1828 return False;
1831 /* Look up the host address in the address list we just got. */
1832 for (i = 0; hp->h_addr_list[i]; i++) {
1833 if (memcmp(hp->h_addr_list[i], (caddr_t) & addr, sizeof(addr)) == 0)
1834 return True;
1838 * The host name does not map to the original host address. Perhaps
1839 * someone has compromised a name server. More likely someone botched
1840 * it, but that could be dangerous, too.
1843 DEBUG(0,("host name/address mismatch: %s != %s\n",
1844 inet_ntoa(addr), hp->h_name));
1845 return False;
1849 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
1850 /******************************************************************
1851 Remove any mount options such as -rsize=2048,wsize=2048 etc.
1852 Based on a fix from <Thomas.Hepper@icem.de>.
1853 *******************************************************************/
1855 static void strip_mount_options( pstring *str)
1857 if (**str == '-')
1859 char *p = *str;
1860 while(*p && !isspace(*p))
1861 p++;
1862 while(*p && isspace(*p))
1863 p++;
1864 if(*p) {
1865 pstring tmp_str;
1867 pstrcpy(tmp_str, p);
1868 pstrcpy(*str, tmp_str);
1873 /*******************************************************************
1874 Patch from jkf@soton.ac.uk
1875 Split Luke's automount_server into YP lookup and string splitter
1876 so can easily implement automount_path().
1877 As we may end up doing both, cache the last YP result.
1878 *******************************************************************/
1880 #ifdef WITH_NISPLUS_HOME
1881 static char *automount_lookup(char *user_name)
1883 static fstring last_key = "";
1884 static pstring last_value = "";
1886 char *nis_map = (char *)lp_nis_home_map_name();
1888 char buffer[NIS_MAXATTRVAL + 1];
1889 nis_result *result;
1890 nis_object *object;
1891 entry_obj *entry;
1893 DEBUG(5, ("NIS+ Domain: %s\n", (char *)nis_local_directory()));
1895 if (strcmp(user_name, last_key))
1897 slprintf(buffer, sizeof(buffer)-1, "[%s=%s]%s.%s", "key", user_name, nis_map,
1898 (char *)nis_local_directory());
1899 DEBUG(5, ("NIS+ querystring: %s\n", buffer));
1901 if (result = nis_list(buffer, RETURN_RESULT, NULL, NULL))
1903 if (result->status != NIS_SUCCESS)
1905 DEBUG(3, ("NIS+ query failed: %s\n", nis_sperrno(result->status)));
1906 fstrcpy(last_key, ""); pstrcpy(last_value, "");
1908 else
1910 object = result->objects.objects_val;
1911 if (object->zo_data.zo_type == ENTRY_OBJ)
1913 entry = &object->zo_data.objdata_u.en_data;
1914 DEBUG(5, ("NIS+ entry type: %s\n", entry->en_type));
1915 DEBUG(3, ("NIS+ result: %s\n", entry->en_cols.en_cols_val[1].ec_value.ec_value_val));
1917 pstrcpy(last_value, entry->en_cols.en_cols_val[1].ec_value.ec_value_val);
1918 string_sub(last_value, "&", user_name);
1919 fstrcpy(last_key, user_name);
1923 nis_freeresult(result);
1926 strip_mount_options(&last_value);
1928 DEBUG(4, ("NIS+ Lookup: %s resulted in %s\n", user_name, last_value));
1929 return last_value;
1931 #else /* WITH_NISPLUS_HOME */
1932 static char *automount_lookup(char *user_name)
1934 static fstring last_key = "";
1935 static pstring last_value = "";
1937 int nis_error; /* returned by yp all functions */
1938 char *nis_result; /* yp_match inits this */
1939 int nis_result_len; /* and set this */
1940 char *nis_domain; /* yp_get_default_domain inits this */
1941 char *nis_map = (char *)lp_nis_home_map_name();
1943 if ((nis_error = yp_get_default_domain(&nis_domain)) != 0)
1945 DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
1946 return last_value;
1949 DEBUG(5, ("NIS Domain: %s\n", nis_domain));
1951 if (!strcmp(user_name, last_key))
1953 nis_result = last_value;
1954 nis_result_len = strlen(last_value);
1955 nis_error = 0;
1957 else
1959 if ((nis_error = yp_match(nis_domain, nis_map,
1960 user_name, strlen(user_name),
1961 &nis_result, &nis_result_len)) != 0)
1963 DEBUG(3, ("YP Error: \"%s\" while looking up \"%s\" in map \"%s\"\n",
1964 yperr_string(nis_error), user_name, nis_map));
1966 if (!nis_error && nis_result_len >= sizeof(pstring))
1968 nis_result_len = sizeof(pstring)-1;
1970 fstrcpy(last_key, user_name);
1971 strncpy(last_value, nis_result, nis_result_len);
1972 last_value[nis_result_len] = '\0';
1975 strip_mount_options(&last_value);
1977 DEBUG(4, ("YP Lookup: %s resulted in %s\n", user_name, last_value));
1978 return last_value;
1980 #endif /* WITH_NISPLUS_HOME */
1981 #endif
1983 /*******************************************************************
1984 Patch from jkf@soton.ac.uk
1985 This is Luke's original function with the NIS lookup code
1986 moved out to a separate function.
1987 *******************************************************************/
1988 static char *automount_server(char *user_name)
1990 static pstring server_name;
1992 /* use the local machine name as the default */
1993 /* this will be the default if WITH_AUTOMOUNT is not used or fails */
1994 pstrcpy(server_name, local_machine);
1996 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
1998 if (lp_nis_home_map())
2000 int home_server_len;
2001 char *automount_value = automount_lookup(user_name);
2002 home_server_len = strcspn(automount_value,":");
2003 DEBUG(5, ("NIS lookup succeeded. Home server length: %d\n",home_server_len));
2004 if (home_server_len > sizeof(pstring))
2006 home_server_len = sizeof(pstring);
2008 strncpy(server_name, automount_value, home_server_len);
2009 server_name[home_server_len] = '\0';
2011 #endif
2013 DEBUG(4,("Home server: %s\n", server_name));
2015 return server_name;
2018 /*******************************************************************
2019 Patch from jkf@soton.ac.uk
2020 Added this to implement %p (NIS auto-map version of %H)
2021 *******************************************************************/
2022 static char *automount_path(char *user_name)
2024 static pstring server_path;
2026 /* use the passwd entry as the default */
2027 /* this will be the default if WITH_AUTOMOUNT is not used or fails */
2028 /* pstrcpy() copes with get_home_dir() returning NULL */
2029 pstrcpy(server_path, get_home_dir(user_name));
2031 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
2033 if (lp_nis_home_map())
2035 char *home_path_start;
2036 char *automount_value = automount_lookup(user_name);
2037 home_path_start = strchr(automount_value,':');
2038 if (home_path_start != NULL)
2040 DEBUG(5, ("NIS lookup succeeded. Home path is: %s\n",
2041 home_path_start?(home_path_start+1):""));
2042 pstrcpy(server_path, home_path_start+1);
2045 #endif
2047 DEBUG(4,("Home server path: %s\n", server_path));
2049 return server_path;
2053 /*******************************************************************
2054 sub strings with useful parameters
2055 Rewritten by Stefaan A Eeckels <Stefaan.Eeckels@ecc.lu> and
2056 Paul Rippin <pr3245@nopc.eurostat.cec.be>
2057 ********************************************************************/
2058 void standard_sub_basic(char *str)
2060 char *s, *p;
2061 char pidstr[10];
2062 struct passwd *pass;
2063 char *username = sam_logon_in_ssb ? samlogon_user : sesssetup_user;
2065 for (s = str ; s && *s && (p = strchr(s,'%')); s = p )
2067 switch (*(p+1))
2069 case 'G' :
2071 if ((pass = Get_Pwnam(username,False))!=NULL)
2073 string_sub(p,"%G",gidtoname(pass->pw_gid));
2075 else
2077 p += 2;
2079 break;
2081 case 'N' : string_sub(p,"%N", automount_server(username)); break;
2082 case 'I' : string_sub(p,"%I", client_addr(Client)); break;
2083 case 'L' : string_sub(p,"%L", local_machine); break;
2084 case 'M' : string_sub(p,"%M", client_name(Client)); break;
2085 case 'R' : string_sub(p,"%R", remote_proto); break;
2086 case 'T' : string_sub(p,"%T", timestring()); break;
2087 case 'U' : string_sub(p,"%U", username); break;
2088 case 'a' : string_sub(p,"%a", remote_arch); break;
2089 case 'd' :
2091 slprintf(pidstr,sizeof(pidstr) - 1, "%d",(int)getpid());
2092 string_sub(p,"%d", pidstr);
2093 break;
2095 case 'h' : string_sub(p,"%h", myhostname); break;
2096 case 'm' : string_sub(p,"%m", remote_machine); break;
2097 case 'v' : string_sub(p,"%v", VERSION); break;
2098 case '$' : /* Expand environment variables */
2100 /* Contributed by Branko Cibej <branko.cibej@hermes.si> */
2101 fstring envname;
2102 char *envval;
2103 char *q, *r;
2104 int copylen;
2106 if (*(p+2) != '(')
2108 p+=2;
2109 break;
2111 if ((q = strchr(p,')')) == NULL)
2113 DEBUG(0,("standard_sub_basic: Unterminated environment \
2114 variable [%s]\n", p));
2115 p+=2;
2116 break;
2119 r = p+3;
2120 copylen = MIN((q-r),(sizeof(envname)-1));
2121 strncpy(envname,r,copylen);
2122 envname[copylen] = '\0';
2124 if ((envval = getenv(envname)) == NULL)
2126 DEBUG(0,("standard_sub_basic: Environment variable [%s] not set\n",
2127 envname));
2128 p+=2;
2129 break;
2132 copylen = MIN((q+1-p),(sizeof(envname)-1));
2133 strncpy(envname,p,copylen);
2134 envname[copylen] = '\0';
2135 string_sub(p,envname,envval);
2136 break;
2138 case '\0': p++; break; /* don't run off end if last character is % */
2139 default : p+=2; break;
2142 return;
2146 /****************************************************************************
2147 do some standard substitutions in a string
2148 ****************************************************************************/
2149 void standard_sub(connection_struct *conn,char *str)
2151 char *p, *s, *home;
2153 for (s=str; (p=strchr(s, '%'));s=p) {
2154 switch (*(p+1)) {
2155 case 'H':
2156 if ((home = get_home_dir(conn->user))) {
2157 string_sub(p,"%H",home);
2158 } else {
2159 p += 2;
2161 break;
2163 case 'P':
2164 string_sub(p,"%P",conn->connectpath);
2165 break;
2167 case 'S':
2168 string_sub(p,"%S",
2169 lp_servicename(SNUM(conn)));
2170 break;
2172 case 'g':
2173 string_sub(p,"%g",
2174 gidtoname(conn->gid));
2175 break;
2176 case 'u':
2177 string_sub(p,"%u",conn->user);
2178 break;
2180 /* Patch from jkf@soton.ac.uk Left the %N (NIS
2181 * server name) in standard_sub_basic as it is
2182 * a feature for logon servers, hence uses the
2183 * username. The %p (NIS server path) code is
2184 * here as it is used instead of the default
2185 * "path =" string in [homes] and so needs the
2186 * service name, not the username. */
2187 case 'p':
2188 string_sub(p,"%p",
2189 automount_path(lp_servicename(SNUM(conn))));
2190 break;
2191 case '\0':
2192 p++;
2193 break; /* don't run off the end of the string
2196 default: p+=2;
2197 break;
2201 standard_sub_basic(str);
2206 /*******************************************************************
2207 are two IPs on the same subnet?
2208 ********************************************************************/
2209 BOOL same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask)
2211 uint32 net1,net2,nmask;
2213 nmask = ntohl(mask.s_addr);
2214 net1 = ntohl(ip1.s_addr);
2215 net2 = ntohl(ip2.s_addr);
2217 return((net1 & nmask) == (net2 & nmask));
2221 /****************************************************************************
2222 a wrapper for gethostbyname() that tries with all lower and all upper case
2223 if the initial name fails
2224 ****************************************************************************/
2225 struct hostent *Get_Hostbyname(const char *name)
2227 char *name2 = strdup(name);
2228 struct hostent *ret;
2230 if (!name2)
2232 DEBUG(0,("Memory allocation error in Get_Hostbyname! panic\n"));
2233 exit(0);
2238 * This next test is redundent and causes some systems (with
2239 * broken isalnum() calls) problems.
2240 * JRA.
2243 #if 0
2244 if (!isalnum(*name2))
2246 free(name2);
2247 return(NULL);
2249 #endif /* 0 */
2251 ret = sys_gethostbyname(name2);
2252 if (ret != NULL)
2254 free(name2);
2255 return(ret);
2258 /* try with all lowercase */
2259 strlower(name2);
2260 ret = sys_gethostbyname(name2);
2261 if (ret != NULL)
2263 free(name2);
2264 return(ret);
2267 /* try with all uppercase */
2268 strupper(name2);
2269 ret = sys_gethostbyname(name2);
2270 if (ret != NULL)
2272 free(name2);
2273 return(ret);
2276 /* nothing works :-( */
2277 free(name2);
2278 return(NULL);
2282 /*******************************************************************
2283 turn a uid into a user name
2284 ********************************************************************/
2285 char *uidtoname(uid_t uid)
2287 static char name[40];
2288 struct passwd *pass = getpwuid(uid);
2289 if (pass) return(pass->pw_name);
2290 slprintf(name, sizeof(name) - 1, "%d",(int)uid);
2291 return(name);
2295 /*******************************************************************
2296 turn a gid into a group name
2297 ********************************************************************/
2299 char *gidtoname(gid_t gid)
2301 static char name[40];
2302 struct group *grp = getgrgid(gid);
2303 if (grp) return(grp->gr_name);
2304 slprintf(name,sizeof(name) - 1, "%d",(int)gid);
2305 return(name);
2308 /*******************************************************************
2309 turn a user name into a uid
2310 ********************************************************************/
2311 uid_t nametouid(const char *name)
2313 struct passwd *pass = getpwnam(name);
2314 if (pass) return(pass->pw_uid);
2315 return (uid_t)-1;
2318 /*******************************************************************
2319 something really nasty happened - panic!
2320 ********************************************************************/
2321 void smb_panic(char *why)
2323 char *cmd = lp_panic_action();
2324 if (cmd && *cmd) {
2325 system(cmd);
2327 DEBUG(0,("PANIC: %s\n", why));
2328 dbgflush();
2329 abort();
2333 /*******************************************************************
2334 a readdir wrapper which just returns the file name
2335 ********************************************************************/
2336 char *readdirname(DIR *p)
2338 SMB_STRUCT_DIRENT *ptr;
2339 char *dname;
2341 if (!p) return(NULL);
2343 ptr = (SMB_STRUCT_DIRENT *)sys_readdir(p);
2344 if (!ptr) return(NULL);
2346 dname = ptr->d_name;
2348 #ifdef NEXT2
2349 if (telldir(p) < 0) return(NULL);
2350 #endif
2352 #ifdef HAVE_BROKEN_READDIR
2353 /* using /usr/ucb/cc is BAD */
2354 dname = dname - 2;
2355 #endif
2358 static pstring buf;
2359 memcpy(buf, dname, NAMLEN(ptr)+1);
2360 dname = buf;
2363 return(dname);
2366 /*******************************************************************
2367 Utility function used to decide if the last component
2368 of a path matches a (possibly wildcarded) entry in a namelist.
2369 ********************************************************************/
2371 BOOL is_in_path(char *name, name_compare_entry *namelist)
2373 pstring last_component;
2374 char *p;
2376 DEBUG(8, ("is_in_path: %s\n", name));
2378 /* if we have no list it's obviously not in the path */
2379 if((namelist == NULL ) || ((namelist != NULL) && (namelist[0].name == NULL)))
2381 DEBUG(8,("is_in_path: no name list.\n"));
2382 return False;
2385 /* Get the last component of the unix name. */
2386 p = strrchr(name, '/');
2387 strncpy(last_component, p ? ++p : name, sizeof(last_component)-1);
2388 last_component[sizeof(last_component)-1] = '\0';
2390 for(; namelist->name != NULL; namelist++)
2392 if(namelist->is_wild)
2395 * Look for a wildcard match. Use the old
2396 * 'unix style' mask match, rather than the
2397 * new NT one.
2399 if (unix_mask_match(last_component, namelist->name, case_sensitive, False))
2401 DEBUG(8,("is_in_path: mask match succeeded\n"));
2402 return True;
2405 else
2407 if((case_sensitive && (strcmp(last_component, namelist->name) == 0))||
2408 (!case_sensitive && (StrCaseCmp(last_component, namelist->name) == 0)))
2410 DEBUG(8,("is_in_path: match succeeded\n"));
2411 return True;
2415 DEBUG(8,("is_in_path: match not found\n"));
2417 return False;
2420 /*******************************************************************
2421 Strip a '/' separated list into an array of
2422 name_compare_enties structures suitable for
2423 passing to is_in_path(). We do this for
2424 speed so we can pre-parse all the names in the list
2425 and don't do it for each call to is_in_path().
2426 namelist is modified here and is assumed to be
2427 a copy owned by the caller.
2428 We also check if the entry contains a wildcard to
2429 remove a potentially expensive call to mask_match
2430 if possible.
2431 ********************************************************************/
2433 void set_namearray(name_compare_entry **ppname_array, char *namelist)
2435 char *name_end;
2436 char *nameptr = namelist;
2437 int num_entries = 0;
2438 int i;
2440 (*ppname_array) = NULL;
2442 if((nameptr == NULL ) || ((nameptr != NULL) && (*nameptr == '\0')))
2443 return;
2445 /* We need to make two passes over the string. The
2446 first to count the number of elements, the second
2447 to split it.
2449 while(*nameptr)
2451 if ( *nameptr == '/' )
2453 /* cope with multiple (useless) /s) */
2454 nameptr++;
2455 continue;
2457 /* find the next / */
2458 name_end = strchr(nameptr, '/');
2460 /* oops - the last check for a / didn't find one. */
2461 if (name_end == NULL)
2462 break;
2464 /* next segment please */
2465 nameptr = name_end + 1;
2466 num_entries++;
2469 if(num_entries == 0)
2470 return;
2472 if(( (*ppname_array) = (name_compare_entry *)malloc(
2473 (num_entries + 1) * sizeof(name_compare_entry))) == NULL)
2475 DEBUG(0,("set_namearray: malloc fail\n"));
2476 return;
2479 /* Now copy out the names */
2480 nameptr = namelist;
2481 i = 0;
2482 while(*nameptr)
2484 if ( *nameptr == '/' )
2486 /* cope with multiple (useless) /s) */
2487 nameptr++;
2488 continue;
2490 /* find the next / */
2491 if ((name_end = strchr(nameptr, '/')) != NULL)
2493 *name_end = 0;
2496 /* oops - the last check for a / didn't find one. */
2497 if(name_end == NULL)
2498 break;
2500 (*ppname_array)[i].is_wild = ((strchr( nameptr, '?')!=NULL) ||
2501 (strchr( nameptr, '*')!=NULL));
2502 if(((*ppname_array)[i].name = strdup(nameptr)) == NULL)
2504 DEBUG(0,("set_namearray: malloc fail (1)\n"));
2505 return;
2508 /* next segment please */
2509 nameptr = name_end + 1;
2510 i++;
2513 (*ppname_array)[i].name = NULL;
2515 return;
2518 /****************************************************************************
2519 routine to free a namearray.
2520 ****************************************************************************/
2522 void free_namearray(name_compare_entry *name_array)
2524 if(name_array == 0)
2525 return;
2527 if(name_array->name != NULL)
2528 free(name_array->name);
2530 free((char *)name_array);
2533 /****************************************************************************
2534 routine to do file locking
2535 ****************************************************************************/
2536 BOOL fcntl_lock(int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
2538 #ifdef HAVE_FCNTL_LOCK
2539 SMB_STRUCT_FLOCK lock;
2540 int ret;
2542 if(lp_ole_locking_compat()) {
2543 SMB_OFF_T mask2= ((SMB_OFF_T)0x3) << (SMB_OFF_T_BITS-4);
2544 SMB_OFF_T mask = (mask2<<2);
2546 /* make sure the count is reasonable, we might kill the lockd otherwise */
2547 count &= ~mask;
2549 /* the offset is often strange - remove 2 of its bits if either of
2550 the top two bits are set. Shift the top ones by two bits. This
2551 still allows OLE2 apps to operate, but should stop lockd from
2552 dieing */
2553 if ((offset & mask) != 0)
2554 offset = (offset & ~mask) | (((offset & mask) >> 2) & mask2);
2555 } else {
2556 SMB_OFF_T mask2 = ((SMB_OFF_T)0x4) << (SMB_OFF_T_BITS-4);
2557 SMB_OFF_T mask = (mask2<<1);
2558 SMB_OFF_T neg_mask = ~mask;
2560 /* interpret negative counts as large numbers */
2561 if (count < 0)
2562 count &= ~mask;
2564 /* no negative offsets */
2565 if(offset < 0)
2566 offset &= ~mask;
2568 /* count + offset must be in range */
2569 while ((offset < 0 || (offset + count < 0)) && mask)
2571 offset &= ~mask;
2572 mask = ((mask >> 1) & neg_mask);
2576 DEBUG(8,("fcntl_lock %d %d %.0f %.0f %d\n",fd,op,(double)offset,(double)count,type));
2578 lock.l_type = type;
2579 lock.l_whence = SEEK_SET;
2580 lock.l_start = offset;
2581 lock.l_len = count;
2582 lock.l_pid = 0;
2584 errno = 0;
2586 ret = fcntl(fd,op,&lock);
2587 if (errno == EFBIG)
2589 if( DEBUGLVL( 0 ))
2591 dbgtext("fcntl_lock: WARNING: lock request at offset %.0f, length %.0f returned\n", (double)offset,(double)count);
2592 dbgtext("a 'file too large' error. This can happen when using 64 bit lock offsets\n");
2593 dbgtext("on 32 bit NFS mounted file systems. Retrying with 32 bit truncated length.\n");
2595 /* 32 bit NFS file system, retry with smaller offset */
2596 errno = 0;
2597 lock.l_len = count & 0xffffffff;
2598 ret = fcntl(fd,op,&lock);
2601 if (errno != 0)
2602 DEBUG(3,("fcntl lock gave errno %d (%s)\n",errno,strerror(errno)));
2604 /* a lock query */
2605 if (op == SMB_F_GETLK)
2607 if ((ret != -1) &&
2608 (lock.l_type != F_UNLCK) &&
2609 (lock.l_pid != 0) &&
2610 (lock.l_pid != getpid()))
2612 DEBUG(3,("fd %d is locked by pid %d\n",fd,(int)lock.l_pid));
2613 return(True);
2616 /* it must be not locked or locked by me */
2617 return(False);
2620 /* a lock set or unset */
2621 if (ret == -1)
2623 DEBUG(3,("lock failed at offset %.0f count %.0f op %d type %d (%s)\n",
2624 (double)offset,(double)count,op,type,strerror(errno)));
2626 /* perhaps it doesn't support this sort of locking?? */
2627 if (errno == EINVAL)
2629 DEBUG(3,("locking not supported? returning True\n"));
2630 return(True);
2633 return(False);
2636 /* everything went OK */
2637 DEBUG(8,("Lock call successful\n"));
2639 return(True);
2640 #else
2641 return(False);
2642 #endif
2645 /*******************************************************************
2646 is the name specified one of my netbios names
2647 returns true is it is equal, false otherwise
2648 ********************************************************************/
2649 BOOL is_myname(char *s)
2651 int n;
2652 BOOL ret = False;
2654 for (n=0; my_netbios_names[n]; n++) {
2655 if (strequal(my_netbios_names[n], s))
2656 ret=True;
2658 DEBUG(8, ("is_myname(\"%s\") returns %d\n", s, ret));
2659 return(ret);
2662 /*******************************************************************
2663 set the horrid remote_arch string based on an enum.
2664 ********************************************************************/
2665 void set_remote_arch(enum remote_arch_types type)
2667 ra_type = type;
2668 switch( type )
2670 case RA_WFWG:
2671 fstrcpy(remote_arch, "WfWg");
2672 return;
2673 case RA_OS2:
2674 fstrcpy(remote_arch, "OS2");
2675 return;
2676 case RA_WIN95:
2677 fstrcpy(remote_arch, "Win95");
2678 return;
2679 case RA_WINNT:
2680 fstrcpy(remote_arch, "WinNT");
2681 return;
2682 case RA_SAMBA:
2683 fstrcpy(remote_arch,"Samba");
2684 return;
2685 default:
2686 ra_type = RA_UNKNOWN;
2687 fstrcpy(remote_arch, "UNKNOWN");
2688 break;
2692 /*******************************************************************
2693 Get the remote_arch type.
2694 ********************************************************************/
2695 enum remote_arch_types get_remote_arch(void)
2697 return ra_type;
2701 /*******************************************************************
2702 align a pointer to a multiple of 2 bytes
2703 ********************************************************************/
2704 char *align2(char *q, char *base)
2706 if ((q - base) & 1)
2708 q++;
2710 return q;
2713 void out_ascii(FILE *f, unsigned char *buf,int len)
2715 int i;
2716 for (i=0;i<len;i++)
2718 fprintf(f, "%c", isprint(buf[i])?buf[i]:'.');
2722 void out_data(FILE *f,char *buf1,int len, int per_line)
2724 unsigned char *buf = (unsigned char *)buf1;
2725 int i=0;
2726 if (len<=0)
2728 return;
2731 fprintf(f, "[%03X] ",i);
2732 for (i=0;i<len;)
2734 fprintf(f, "%02X ",(int)buf[i]);
2735 i++;
2736 if (i%(per_line/2) == 0) fprintf(f, " ");
2737 if (i%per_line == 0)
2739 out_ascii(f,&buf[i-per_line ],per_line/2); fprintf(f, " ");
2740 out_ascii(f,&buf[i-per_line/2],per_line/2); fprintf(f, "\n");
2741 if (i<len) fprintf(f, "[%03X] ",i);
2744 if ((i%per_line) != 0)
2746 int n;
2748 n = per_line - (i%per_line);
2749 fprintf(f, " ");
2750 if (n>(per_line/2)) fprintf(f, " ");
2751 while (n--)
2753 fprintf(f, " ");
2755 n = MIN(per_line/2,i%per_line);
2756 out_ascii(f,&buf[i-(i%per_line)],n); fprintf(f, " ");
2757 n = (i%per_line) - n;
2758 if (n>0) out_ascii(f,&buf[i-n],n);
2759 fprintf(f, "\n");
2763 void print_asc(int level, unsigned char *buf,int len)
2765 int i;
2766 for (i=0;i<len;i++)
2767 DEBUG(level,("%c", isprint(buf[i])?buf[i]:'.'));
2770 void dump_data(int level,char *buf1,int len)
2772 unsigned char *buf = (unsigned char *)buf1;
2773 int i=0;
2774 if (len<=0) return;
2776 DEBUG(level,("[%03X] ",i));
2777 for (i=0;i<len;) {
2778 DEBUG(level,("%02X ",(int)buf[i]));
2779 i++;
2780 if (i%8 == 0) DEBUG(level,(" "));
2781 if (i%16 == 0) {
2782 print_asc(level,&buf[i-16],8); DEBUG(level,(" "));
2783 print_asc(level,&buf[i-8],8); DEBUG(level,("\n"));
2784 if (i<len) DEBUG(level,("[%03X] ",i));
2787 if (i%16) {
2788 int n;
2790 n = 16 - (i%16);
2791 DEBUG(level,(" "));
2792 if (n>8) DEBUG(level,(" "));
2793 while (n--) DEBUG(level,(" "));
2795 n = MIN(8,i%16);
2796 print_asc(level,&buf[i-(i%16)],n); DEBUG(level,(" "));
2797 n = (i%16) - n;
2798 if (n>0) print_asc(level,&buf[i-n],n);
2799 DEBUG(level,("\n"));
2803 char *tab_depth(int depth)
2805 static pstring spaces;
2806 memset(spaces, ' ', depth * 4);
2807 spaces[depth * 4] = 0;
2808 return spaces;
2811 /*****************************************************************************
2812 * Provide a checksum on a string
2814 * Input: s - the null-terminated character string for which the checksum
2815 * will be calculated.
2817 * Output: The checksum value calculated for s.
2819 * ****************************************************************************
2821 int str_checksum(const char *s)
2823 int res = 0;
2824 int c;
2825 int i=0;
2827 while(*s) {
2828 c = *s;
2829 res ^= (c << (i % 15)) ^ (c >> (15-(i%15)));
2830 s++;
2831 i++;
2833 return(res);
2834 } /* str_checksum */
2838 /*****************************************************************
2839 zero a memory area then free it. Used to catch bugs faster
2840 *****************************************************************/
2841 void zero_free(void *p, size_t size)
2843 memset(p, 0, size);
2844 free(p);
2848 /*****************************************************************
2849 set our open file limit to a requested max and return the limit
2850 *****************************************************************/
2851 int set_maxfiles(int requested_max)
2853 #if (defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE))
2854 struct rlimit rlp;
2855 int saved_current_limit;
2857 if(getrlimit(RLIMIT_NOFILE, &rlp)) {
2858 DEBUG(0,("set_maxfiles: getrlimit (1) for RLIMIT_NOFILE failed with error %s\n",
2859 strerror(errno) ));
2860 /* just guess... */
2861 return requested_max;
2865 * Set the fd limit to be real_max_open_files + MAX_OPEN_FUDGEFACTOR to
2866 * account for the extra fd we need
2867 * as well as the log files and standard
2868 * handles etc. Save the limit we want to set in case
2869 * we are running on an OS that doesn't support this limit (AIX)
2870 * which always returns RLIM_INFINITY for rlp.rlim_max.
2873 saved_current_limit = rlp.rlim_cur = MIN(requested_max,rlp.rlim_max);
2875 if(setrlimit(RLIMIT_NOFILE, &rlp)) {
2876 DEBUG(0,("set_maxfiles: setrlimit for RLIMIT_NOFILE for %d files failed with error %s\n",
2877 (int)rlp.rlim_cur, strerror(errno) ));
2878 /* just guess... */
2879 return saved_current_limit;
2882 if(getrlimit(RLIMIT_NOFILE, &rlp)) {
2883 DEBUG(0,("set_maxfiles: getrlimit (2) for RLIMIT_NOFILE failed with error %s\n",
2884 strerror(errno) ));
2885 /* just guess... */
2886 return saved_current_limit;
2889 #if defined(RLIM_INFINITY)
2890 if(rlp.rlim_cur == RLIM_INFINITY)
2891 return saved_current_limit;
2892 #endif
2894 if((int)rlp.rlim_cur > saved_current_limit)
2895 return saved_current_limit;
2897 return rlp.rlim_cur;
2898 #else /* !defined(HAVE_GETRLIMIT) || !defined(RLIMIT_NOFILE) */
2900 * No way to know - just guess...
2902 return requested_max;
2903 #endif
2906 #if 0
2907 /*****************************************************************
2908 splits out the last subkey of a key
2909 *****************************************************************/
2910 void reg_get_subkey(char *full_keyname, char *key_name, char *subkey_name)
2912 split_at_last_component(full_keyname, key_name, '\\', subkey_name);
2915 /*****************************************************************
2916 splits out the start of the key (HKLM or HKU) and the rest of the key
2917 *****************************************************************/
2918 BOOL reg_split_key(char *full_keyname, uint32 *reg_type, char *key_name)
2920 pstring tmp;
2922 if (!next_token(&full_keyname, tmp, "\\", sizeof(tmp)))
2924 return False;
2927 (*reg_type) = 0;
2929 DEBUG(10, ("reg_split_key: hive %s\n", tmp));
2931 if (strequal(tmp, "HKLM") || strequal(tmp, "HKEY_LOCAL_MACHINE"))
2933 (*reg_type) = HKEY_LOCAL_MACHINE;
2935 else if (strequal(tmp, "HKU") || strequal(tmp, "HKEY_USERS"))
2937 (*reg_type) = HKEY_USERS;
2939 else
2941 DEBUG(10,("reg_split_key: unrecognised hive key %s\n", tmp));
2942 return False;
2945 if (next_token(NULL, tmp, "\n\r", sizeof(tmp)))
2947 fstrcpy(key_name, tmp);
2949 else
2951 key_name[0] = 0;
2954 DEBUG(10, ("reg_split_key: name %s\n", key_name));
2956 return True;
2958 #endif