2 Unix SMB/Netbios implementation.
4 Samba utility functions
5 Copyright (C) Andrew Tridgell 1992-1995
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.
31 int Protocol = PROTOCOL_COREPLUS;
35 /* a default finfo structure to ensure all fields are sensible */
36 file_info def_finfo = {-1,0,0,0,0,0,0,""};
38 /* these are some file handles where debug info will be stored */
41 /* the client file descriptor */
44 /* info on the client */
45 struct from_host Client_info=
46 {"UNKNOWN","0.0.0.0",NULL};
48 /* the last IP received from */
49 struct in_addr lastip;
51 /* the last port received from */
54 /* my IP, the broadcast IP and the Netmask */
56 struct in_addr bcast_ip;
57 struct in_addr Netmask;
62 case handling on filenames
64 int case_default = CASE_LOWER;
67 /* size of reads during a direct file to file transfer */
68 int ReadSize = 16*1024;
70 pstring debugf = "/tmp/log.samba";
73 /* the following control case operations - they are put here so the
74 client can link easily */
77 BOOL use_mangled_map = False;
78 BOOL short_case_preserve;
81 fstring remote_machine="";
82 fstring local_machine="";
83 fstring remote_arch="UNKNOWN";
84 fstring remote_proto="UNKNOWN";
85 pstring myhostname="";
86 pstring user_socket_options="";
87 pstring sesssetup_user="";
90 static char *filename_dos(char *path,char *buf);
92 static BOOL stdout_logging = False;
95 /*******************************************************************
96 get ready for syslog stuff
97 ******************************************************************/
98 void setup_logging(char *pname,BOOL interactive)
102 char *p = strrchr(pname,'/');
104 openlog(pname, LOG_PID, LOG_DAEMON);
108 stdout_logging = True;
114 BOOL append_log=False;
117 /****************************************************************************
119 ****************************************************************************/
120 void reopen_logs(void)
127 strcpy(fname,debugf);
128 if (lp_loaded() && (*lp_logfile()))
129 strcpy(fname,lp_logfile());
131 if (!strcsequal(fname,debugf) || !dbf || !file_exist(debugf,NULL))
133 strcpy(debugf,fname);
134 if (dbf) fclose(dbf);
136 dbf = fopen(debugf,"a");
138 dbf = fopen(debugf,"w");
139 if (dbf) setbuf(dbf,NULL);
153 /*******************************************************************
154 write an debug message on the debugfile. This is called by the DEBUG
156 ********************************************************************/
158 int Debug1(char *format_str, ...)
169 va_start(ap, format_str);
172 format_str = va_arg(ap,char *);
175 if (stdout_logging) {
176 vfprintf(dbf,format_str,ap);
182 static int debug_count=0;
185 if (debug_count == 100) {
186 int maxlog = lp_max_log_size() * 1024;
187 if (dbf && maxlog > 0)
191 if (fstat(fileno(dbf),&st) == 0 && st.st_size > maxlog) {
192 fclose(dbf); dbf = NULL;
194 if (dbf && file_size(debugf) > maxlog) {
196 fclose(dbf); dbf = NULL;
197 sprintf(name,"%s.old",debugf);
198 sys_rename(debugf,name);
208 if (!lp_syslog_only())
213 dbf = fopen(debugf,"w");
222 if (syslog_level < lp_syslog())
225 * map debug levels to syslog() priorities
226 * note that not all DEBUG(0, ...) calls are
229 static int priority_map[] = {
238 if (syslog_level >= sizeof(priority_map) / sizeof(priority_map[0]) ||
240 priority = LOG_DEBUG;
242 priority = priority_map[syslog_level];
244 vsprintf(msgbuf, format_str, ap);
247 syslog(priority, "%s", msgbuf);
252 if (!lp_syslog_only())
255 vfprintf(dbf,format_str,ap);
263 /****************************************************************************
264 routine to do file locking
265 ****************************************************************************/
266 BOOL fcntl_lock(int fd,int op,uint32 offset,uint32 count,int type)
273 uint32 mask = 0xC0000000;
275 /* make sure the count is reasonable, we might kill the lockd otherwise */
278 /* the offset is often strange - remove 2 of its bits if either of
279 the top two bits are set. Shift the top ones by two bits. This
280 still allows OLE2 apps to operate, but should stop lockd from
282 if ((offset & mask) != 0)
283 offset = (offset & ~mask) | ((offset & mask) >> 2);
285 unsigned long mask = ((unsigned)1<<31);
287 /* interpret negative counts as large numbers */
291 /* no negative offsets */
294 /* count + offset must be in range */
295 while ((offset < 0 || (offset + count < 0)) && mask)
303 DEBUG(5,("fcntl_lock %d %d %d %d %d\n",fd,op,(int)offset,(int)count,type));
306 lock.l_whence = SEEK_SET;
307 lock.l_start = (int)offset;
308 lock.l_len = (int)count;
313 ret = fcntl(fd,op,&lock);
316 DEBUG(3,("fcntl lock gave errno %d (%s)\n",errno,strerror(errno)));
322 (lock.l_type != F_UNLCK) &&
324 (lock.l_pid != getpid()))
326 DEBUG(3,("fd %d is locked by pid %d\n",fd,lock.l_pid));
330 /* it must be not locked or locked by me */
334 /* a lock set or unset */
337 DEBUG(3,("lock failed at offset %d count %d op %d type %d (%s)\n",
338 offset,count,op,type,strerror(errno)));
340 /* perhaps it doesn't support this sort of locking?? */
343 DEBUG(3,("locking not supported? returning True\n"));
350 /* everything went OK */
351 DEBUG(5,("Lock call successful\n"));
359 /*******************************************************************
360 lock a file - returning a open file descriptor or -1 on failure
361 The timeout is in seconds. 0 means no timeout
362 ********************************************************************/
363 int file_lock(char *name,int timeout)
365 int fd = open(name,O_RDWR|O_CREAT,0666);
367 if (fd < 0) return(-1);
370 if (timeout) t = time(NULL);
371 while (!timeout || (time(NULL)-t < timeout)) {
372 if (fcntl_lock(fd,F_SETLK,0,1,F_WRLCK)) return(fd);
373 msleep(LOCK_RETRY_TIMEOUT);
381 /*******************************************************************
382 unlock a file locked by file_lock
383 ********************************************************************/
384 void file_unlock(int fd)
388 fcntl_lock(fd,F_SETLK,0,1,F_UNLCK);
393 /*******************************************************************
394 a gettimeofday wrapper
395 ********************************************************************/
396 void GetTimeOfDay(struct timeval *tval)
401 gettimeofday(tval,NULL);
405 int extra_time_offset = 0;
407 static int timediff = 0;
409 /*******************************************************************
410 init the time differences
411 ********************************************************************/
414 struct tm tm_utc,tm_local;
419 tm_utc = *(gmtime(&t));
420 tm_local = *(localtime(&t));
423 timediff = -tm_local.tm_gmtoff;
425 timediff = mktime(&tm_utc) - mktime(&tm_local);
428 if (serverzone == 0) {
429 serverzone = timediff - DSTDiff(t);
430 DEBUG(4,("Serverzone is %d\n",serverzone));
435 /*******************************************************************
436 return the DST offset for a particular time
437 We keep a table of DST offsets to prevent calling localtime() on each
438 call of this function. This saves a LOT of time on many unixes.
439 ********************************************************************/
440 int DSTDiff(time_t t)
442 static struct dst_table {time_t start,end; BOOL is_dst;} *dst_table = NULL;
443 static int table_size = 0;
447 if (t == 0) t = time(NULL);
450 for (i=0;i<table_size;i++)
451 if (t >= dst_table[i].start && t <= dst_table[i].end) break;
454 is_dst = dst_table[i].is_dst;
458 dst_table = (struct dst_table *)Realloc(dst_table,
459 sizeof(dst_table[0])*(i+1));
467 dst_table[i].is_dst = is_dst = (localtime(&t)->tm_isdst?True:False);;
468 dst_table[i].start = dst_table[i].end = t;
470 /* no entry will cover more than 6 months */
471 low = t - 3*30*24*60*60;
472 high = t + 3*30*24*60*60;
474 /* widen the new entry using two bisection searches */
475 while (low+60*60 < dst_table[i].start) {
476 t = low + (dst_table[i].start-low)/2;
477 if ((localtime(&t)->tm_isdst?True:False) == is_dst)
478 dst_table[i].start = t;
483 while (high-60*60 > dst_table[i].end) {
484 t = high + (high-dst_table[i].end)/2;
485 if ((localtime(&t)->tm_isdst?True:False) == is_dst)
486 dst_table[i].end = t;
492 DEBUG(1,("Added DST entry from %s ",
493 asctime(localtime(&dst_table[i].start))));
494 DEBUG(1,("to %s (%d)\n",asctime(localtime(&dst_table[i].end)),
495 dst_table[i].is_dst));
500 return((is_dst?60*60:0) - (extra_time_offset*60));
503 /****************************************************************************
504 return the difference between local and GMT time
505 ****************************************************************************/
506 int TimeDiff(time_t t)
508 static BOOL initialised = False;
509 if (!initialised) {initialised=True; TimeInit();}
510 return(timediff - DSTDiff(t));
513 /****************************************************************************
514 try to optimise the localtime call, it can be quite expenive on some machines
515 timemul is normally LOCAL_TO_GMT, GMT_TO_LOCAL or 0
516 ****************************************************************************/
517 struct tm *LocalTime(time_t *t,int timemul)
522 t2 += timemul * TimeDiff(t2);
528 /****************************************************************************
529 determine if a file descriptor is in fact a socket
530 ****************************************************************************/
531 BOOL is_a_socket(int fd)
535 return(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0);
539 static char *last_ptr=NULL;
541 /****************************************************************************
542 Get the next token from a string, return False if none found
543 handles double-quotes.
544 Based on a routine by GJC@VILLAGE.COM.
545 Extensively modified by Andrew.Tridgell@anu.edu.au
546 ****************************************************************************/
547 BOOL next_token(char **ptr,char *buff,char *sep)
552 if (!ptr) ptr = &last_ptr;
553 if (!ptr) return(False);
557 /* default to simple separators */
558 if (!sep) sep = " \t\n\r";
560 /* find the first non sep char */
561 while(*s && strchr(sep,*s)) s++;
564 if (! *s) return(False);
566 /* copy over the token */
567 for (quoted = False; *s && (quoted || !strchr(sep,*s)); s++)
575 *ptr = (*s) ? s+1 : s;
582 /****************************************************************************
583 Convert list of tokens to array; dependent on above routine.
584 Uses last_ptr from above - bit of a hack.
585 ****************************************************************************/
586 char **toktocliplist(int *ctok, char *sep)
592 if (!sep) sep = " \t\n\r";
594 while(*s && strchr(sep,*s)) s++;
597 if (!*s) return(NULL);
601 while(*s && (!strchr(sep,*s))) s++;
602 while(*s && strchr(sep,*s)) *s++=0;
608 if (!(ret=iret=malloc(ictok*sizeof(char *)))) return NULL;
620 /*******************************************************************
621 safely copies memory, ensuring no overlap problems.
622 this is only used if the machine does not have it's own memmove().
623 this is not the fastest algorithm in town, but it will do for our
625 ********************************************************************/
626 void *MemMove(void *dest,void *src,int size)
630 if (dest==src || !size) return(dest);
632 d = (unsigned long)dest;
633 s = (unsigned long)src;
635 if ((d >= (s+size)) || (s >= (d+size))) {
637 memcpy(dest,src,size);
643 /* we can forward copy */
644 if (s-d >= sizeof(int) &&
645 !(s%sizeof(int)) && !(d%sizeof(int)) && !(size%sizeof(int))) {
646 /* do it all as words */
647 int *idest = (int *)dest;
648 int *isrc = (int *)src;
650 for (i=0;i<size;i++) idest[i] = isrc[i];
653 char *cdest = (char *)dest;
654 char *csrc = (char *)src;
655 for (i=0;i<size;i++) cdest[i] = csrc[i];
660 /* must backward copy */
661 if (d-s >= sizeof(int) &&
662 !(s%sizeof(int)) && !(d%sizeof(int)) && !(size%sizeof(int))) {
663 /* do it all as words */
664 int *idest = (int *)dest;
665 int *isrc = (int *)src;
667 for (i=size-1;i>=0;i--) idest[i] = isrc[i];
670 char *cdest = (char *)dest;
671 char *csrc = (char *)src;
672 for (i=size-1;i>=0;i--) cdest[i] = csrc[i];
680 /****************************************************************************
681 prompte a dptr (to make it recently used)
682 ****************************************************************************/
683 void array_promote(char *array,int elsize,int element)
689 p = (char *)malloc(elsize);
693 DEBUG(5,("Ahh! Can't malloc\n"));
696 memcpy(p,array + element * elsize, elsize);
697 memmove(array + elsize,array,elsize*element);
698 memcpy(array,p,elsize);
702 enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON};
711 } socket_options[] = {
712 {"SO_KEEPALIVE", SOL_SOCKET, SO_KEEPALIVE, 0, OPT_BOOL},
713 {"SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR, 0, OPT_BOOL},
714 {"SO_BROADCAST", SOL_SOCKET, SO_BROADCAST, 0, OPT_BOOL},
716 {"TCP_NODELAY", IPPROTO_TCP, TCP_NODELAY, 0, OPT_BOOL},
718 #ifdef IPTOS_LOWDELAY
719 {"IPTOS_LOWDELAY", IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY, OPT_ON},
721 #ifdef IPTOS_THROUGHPUT
722 {"IPTOS_THROUGHPUT", IPPROTO_IP, IP_TOS, IPTOS_THROUGHPUT, OPT_ON},
725 {"SO_SNDBUF", SOL_SOCKET, SO_SNDBUF, 0, OPT_INT},
728 {"SO_RCVBUF", SOL_SOCKET, SO_RCVBUF, 0, OPT_INT},
731 {"SO_SNDLOWAT", SOL_SOCKET, SO_SNDLOWAT, 0, OPT_INT},
734 {"SO_RCVLOWAT", SOL_SOCKET, SO_RCVLOWAT, 0, OPT_INT},
740 /****************************************************************************
741 set user socket options
742 ****************************************************************************/
743 void set_socket_options(int fd, char *options)
747 while (next_token(&options,tok," \t,"))
752 BOOL got_value = False;
754 if ((p = strchr(tok,'=')))
761 for (i=0;socket_options[i].name;i++)
762 if (strequal(socket_options[i].name,tok))
765 if (!socket_options[i].name)
767 DEBUG(0,("Unknown socket option %s\n",tok));
771 switch (socket_options[i].opttype)
775 ret = setsockopt(fd,socket_options[i].level,
776 socket_options[i].option,(char *)&value,sizeof(int));
781 DEBUG(0,("syntax error - %s does not take a value\n",tok));
784 int on = socket_options[i].value;
785 ret = setsockopt(fd,socket_options[i].level,
786 socket_options[i].option,(char *)&on,sizeof(int));
792 DEBUG(0,("Failed to set socket option %s\n",tok));
798 /****************************************************************************
799 close the socket communication
800 ****************************************************************************/
801 void close_sockets(void )
807 /****************************************************************************
808 return the date and time as a string
809 ****************************************************************************/
810 char *timestring(void )
812 static char TimeBuf[100];
816 strcpy(TimeBuf, asctime(LocalTime(&t,GMT_TO_LOCAL)));
817 #elif defined(CLIX) || defined(CONVEX)
818 strftime(TimeBuf,100,"%m/%d/%y %I:%M:%S %p",LocalTime(&t,GMT_TO_LOCAL));
820 strftime(TimeBuf,100,"%D %r",LocalTime(&t,GMT_TO_LOCAL));
821 #elif defined(TZ_TIME)
823 strftime(TimeBuf,100,"%D:%T",LocalTime(&t,0));
824 sprintf(TimeBuf+strlen(TimeBuf)," %+03d%02d",
825 -TimeDiff(t)/(60*60),-(TimeDiff(t)/60)%60);
828 strftime(TimeBuf,100,"%D %T",LocalTime(&t,GMT_TO_LOCAL));
833 /****************************************************************************
834 determine whether we are in the specified group
835 ****************************************************************************/
836 BOOL in_group(gid_t group, int current_gid, int ngroups, int *groups)
840 if (group == current_gid) return(True);
842 for (i=0;i<ngroups;i++)
843 if (group == groups[i])
849 /****************************************************************************
850 this is a safer strcpy(), meant to prevent core dumps when nasty things happen
851 ****************************************************************************/
852 char *StrCpy(char *dest,char *src)
857 /* I don't want to get lazy with these ... */
859 DEBUG(0,("ERROR: NULL StrCpy() called!\n"));
864 if (!dest) return(NULL);
869 while ((*d++ = *src++)) ;
873 /****************************************************************************
874 line strncpy but always null terminates. Make sure there is room!
875 ****************************************************************************/
876 char *StrnCpy(char *dest,const char *src,int n)
879 if (!dest) return(NULL);
884 while (n-- && (*d++ = *src++)) ;
890 /*******************************************************************
891 copy an IP address from one buffer to another
892 ********************************************************************/
893 void putip(void *dest,void *src)
899 /****************************************************************************
900 interpret the weird netbios "name". Return the name type
901 ****************************************************************************/
902 static int name_interpret(char *in,char *out)
905 int len = (*in++) / 2;
909 if (len > 30 || len<1) return(0);
913 if (in[0] < 'A' || in[0] > 'P' || in[1] < 'A' || in[1] > 'P') {
917 *out = ((in[0]-'A')<<4) + (in[1]-'A');
925 /* Handle any scope names */
928 *out++ = '.'; /* Scope names are separated by periods */
929 len = *(unsigned char *)in++;
930 StrnCpy(out, in, len);
939 /****************************************************************************
940 mangle a name into netbios format
941 ****************************************************************************/
942 int name_mangle(char *In,char *Out,char name_type)
946 char *in = (char *)&buf[0];
947 char *out = (char *)Out;
952 StrnCpy(name,In,sizeof(name)-1);
953 sprintf(buf,"%-15.15s%c",name,name_type);
956 memset(&buf[1],0,16);
961 char c = toupper(in[i]);
962 out[i*2] = (c>>4) + 'A';
963 out[i*2+1] = (c & 0xF) + 'A';
971 p = strchr(label, '.');
973 p = label + strlen(label);
975 memcpy(out, label, p - label);
977 label += p - label + (*p == '.');
980 return(name_len(Out));
984 /*******************************************************************
985 check if a file exists
986 ********************************************************************/
987 BOOL file_exist(char *fname,struct stat *sbuf)
990 if (!sbuf) sbuf = &st;
992 if (sys_stat(fname,sbuf) != 0)
995 return(S_ISREG(sbuf->st_mode));
998 /*******************************************************************
999 check a files mod time
1000 ********************************************************************/
1001 time_t file_modtime(char *fname)
1005 if (sys_stat(fname,&st) != 0)
1008 return(st.st_mtime);
1011 /*******************************************************************
1012 check if a directory exists
1013 ********************************************************************/
1014 BOOL directory_exist(char *dname,struct stat *st)
1019 if (sys_stat(dname,st) != 0)
1022 return(S_ISDIR(st->st_mode));
1025 /*******************************************************************
1026 returns the size in bytes of the named file
1027 ********************************************************************/
1028 uint32 file_size(char *file_name)
1032 sys_stat(file_name,&buf);
1033 return(buf.st_size);
1036 /****************************************************************************
1037 check if it's a null mtime
1038 ****************************************************************************/
1039 static BOOL null_mtime(time_t mtime)
1041 if (mtime == 0 || mtime == 0xFFFFFFFF)
1046 /*******************************************************************
1047 create a 16 bit dos packed date
1048 ********************************************************************/
1049 static uint16 make_dos_date1(time_t unixdate,struct tm *t)
1052 ret = (((unsigned)(t->tm_mon+1)) >> 3) | ((t->tm_year-80) << 1);
1053 ret = ((ret&0xFF)<<8) | (t->tm_mday | (((t->tm_mon+1) & 0x7) << 5));
1057 /*******************************************************************
1058 create a 16 bit dos packed time
1059 ********************************************************************/
1060 static uint16 make_dos_time1(time_t unixdate,struct tm *t)
1063 ret = ((((unsigned)t->tm_min >> 3)&0x7) | (((unsigned)t->tm_hour) << 3));
1064 ret = ((ret&0xFF)<<8) | ((t->tm_sec/2) | ((t->tm_min & 0x7) << 5));
1068 /*******************************************************************
1069 create a 32 bit dos packed date/time from some parameters
1070 This takes a GMT time and returns a packed localtime structure
1071 ********************************************************************/
1072 static uint32 make_dos_date(time_t unixdate)
1077 t = LocalTime(&unixdate,GMT_TO_LOCAL);
1079 ret = make_dos_date1(unixdate,t);
1080 ret = ((ret&0xFFFF)<<16) | make_dos_time1(unixdate,t);
1085 /*******************************************************************
1086 put a dos date into a buffer (time/date format)
1087 This takes GMT time and puts local time in the buffer
1088 ********************************************************************/
1089 void put_dos_date(char *buf,int offset,time_t unixdate)
1091 uint32 x = make_dos_date(unixdate);
1092 SIVAL(buf,offset,x);
1095 /*******************************************************************
1096 put a dos date into a buffer (date/time format)
1097 This takes GMT time and puts local time in the buffer
1098 ********************************************************************/
1099 void put_dos_date2(char *buf,int offset,time_t unixdate)
1101 uint32 x = make_dos_date(unixdate);
1102 x = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16);
1103 SIVAL(buf,offset,x);
1106 /*******************************************************************
1107 put a dos 32 bit "unix like" date into a buffer. This routine takes
1108 GMT and converts it to LOCAL time before putting it (most SMBs assume
1109 localtime for this sort of date)
1110 ********************************************************************/
1111 void put_dos_date3(char *buf,int offset,time_t unixdate)
1113 if (!null_mtime(unixdate))
1114 unixdate += GMT_TO_LOCAL*TimeDiff(unixdate);
1115 SIVAL(buf,offset,unixdate);
1118 /*******************************************************************
1119 interpret a 32 bit dos packed date/time to some parameters
1120 ********************************************************************/
1121 static void interpret_dos_date(uint32 date,int *year,int *month,int *day,int *hour,int *minute,int *second)
1125 p0=date&0xFF; p1=((date&0xFF00)>>8)&0xFF;
1126 p2=((date&0xFF0000)>>16)&0xFF; p3=((date&0xFF000000)>>24)&0xFF;
1128 *second = 2*(p0 & 0x1F);
1129 *minute = ((p0>>5)&0xFF) + ((p1&0x7)<<3);
1130 *hour = (p1>>3)&0xFF;
1132 *month = ((p2>>5)&0xFF) + ((p3&0x1)<<3) - 1;
1133 *year = ((p3>>1)&0xFF) + 80;
1136 /*******************************************************************
1137 create a unix date (int GMT) from a dos date (which is actually in
1139 ********************************************************************/
1140 time_t make_unix_date(void *date_ptr)
1146 dos_date = IVAL(date_ptr,0);
1148 if (dos_date == 0) return(0);
1150 interpret_dos_date(dos_date,&t.tm_year,&t.tm_mon,
1151 &t.tm_mday,&t.tm_hour,&t.tm_min,&t.tm_sec);
1156 /* mktime() also does the local to GMT time conversion for us. XXXXX
1157 Do all unixes do this the same?? */
1163 /*******************************************************************
1164 like make_unix_date() but the words are reversed
1165 ********************************************************************/
1166 time_t make_unix_date2(void *date_ptr)
1170 x = IVAL(date_ptr,0);
1171 x2 = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16);
1174 return(make_unix_date((void *)&x));
1177 /*******************************************************************
1178 create a unix GMT date from a dos date in 32 bit "unix like" format
1179 these generally arrive as localtimes, with corresponding DST
1180 ********************************************************************/
1181 time_t make_unix_date3(void *date_ptr)
1183 time_t t = IVAL(date_ptr,0);
1185 t += LOCAL_TO_GMT*TimeDiff(t);
1189 /*******************************************************************
1190 return a string representing an attribute for a file
1191 ********************************************************************/
1192 char *attrib_string(int mode)
1194 static char attrstr[10];
1198 if (mode & aVOLID) strcat(attrstr,"V");
1199 if (mode & aDIR) strcat(attrstr,"D");
1200 if (mode & aARCH) strcat(attrstr,"A");
1201 if (mode & aHIDDEN) strcat(attrstr,"H");
1202 if (mode & aSYSTEM) strcat(attrstr,"S");
1203 if (mode & aRONLY) strcat(attrstr,"R");
1209 /*******************************************************************
1210 case insensitive string compararison
1211 ********************************************************************/
1212 int StrCaseCmp(char *s, char *t)
1214 for (; tolower(*s) == tolower(*t); ++s, ++t)
1217 return tolower(*s) - tolower(*t);
1220 /*******************************************************************
1221 case insensitive string compararison, length limited
1222 ********************************************************************/
1223 int StrnCaseCmp(char *s, char *t, int n)
1225 while (n-- && *s && *t) {
1226 if (tolower(*s) != tolower(*t)) return(tolower(*s) - tolower(*t));
1229 if (n) return(tolower(*s) - tolower(*t));
1234 /*******************************************************************
1236 ********************************************************************/
1237 BOOL strequal(char *s1,char *s2)
1239 if (s1 == s2) return(True);
1240 if (!s1 || !s2) return(False);
1242 return(StrCaseCmp(s1,s2)==0);
1245 /*******************************************************************
1246 compare 2 strings up to and including the nth char.
1247 ******************************************************************/
1248 BOOL strnequal(char *s1,char *s2,int n)
1250 if (s1 == s2) return(True);
1251 if (!s1 || !s2 || !n) return(False);
1253 return(StrnCaseCmp(s1,s2,n)==0);
1256 /*******************************************************************
1257 compare 2 strings (case sensitive)
1258 ********************************************************************/
1259 BOOL strcsequal(char *s1,char *s2)
1261 if (s1 == s2) return(True);
1262 if (!s1 || !s2) return(False);
1264 return(strcmp(s1,s2)==0);
1268 /*******************************************************************
1269 convert a string to lower case
1270 ********************************************************************/
1271 void strlower(char *s)
1276 if (is_shift_jis (*s)) {
1278 } else if (is_kana (*s)) {
1293 /*******************************************************************
1294 convert a string to upper case
1295 ********************************************************************/
1296 void strupper(char *s)
1301 if (is_shift_jis (*s)) {
1303 } else if (is_kana (*s)) {
1318 /*******************************************************************
1319 convert a string to "normal" form
1320 ********************************************************************/
1321 void strnorm(char *s)
1323 if (case_default == CASE_UPPER)
1329 /*******************************************************************
1330 check if a string is in "normal" case
1331 ********************************************************************/
1332 BOOL strisnormal(char *s)
1334 if (case_default == CASE_UPPER)
1335 return(!strhaslower(s));
1337 return(!strhasupper(s));
1341 /****************************************************************************
1343 ****************************************************************************/
1344 void string_replace(char *s,char oldc,char newc)
1349 if (is_shift_jis (*s)) {
1351 } else if (is_kana (*s)) {
1366 /****************************************************************************
1367 make a file into unix format
1368 ****************************************************************************/
1369 void unix_format(char *fname)
1372 string_replace(fname,'\\','/');
1374 dos2unix_format(fname, True);
1379 strcpy(namecopy,fname);
1381 strcat(fname,namecopy);
1385 /****************************************************************************
1386 make a file into dos format
1387 ****************************************************************************/
1388 void dos_format(char *fname)
1391 unix2dos_format(fname, True);
1393 string_replace(fname,'/','\\');
1397 /*******************************************************************
1398 show a smb message structure
1399 ********************************************************************/
1400 void show_msg(char *buf)
1407 DEBUG(5,("size=%d\nsmb_com=0x%x\nsmb_rcls=%d\nsmb_reh=%d\nsmb_err=%d\nsmb_flg=%d\nsmb_flg2=%d\n",
1409 (int)CVAL(buf,smb_com),
1410 (int)CVAL(buf,smb_rcls),
1411 (int)CVAL(buf,smb_reh),
1412 (int)SVAL(buf,smb_err),
1413 (int)CVAL(buf,smb_flg),
1414 (int)SVAL(buf,smb_flg2)));
1415 DEBUG(5,("smb_tid=%d\nsmb_pid=%d\nsmb_uid=%d\nsmb_mid=%d\nsmt_wct=%d\n",
1416 (int)SVAL(buf,smb_tid),
1417 (int)SVAL(buf,smb_pid),
1418 (int)SVAL(buf,smb_uid),
1419 (int)SVAL(buf,smb_mid),
1420 (int)CVAL(buf,smb_wct)));
1421 for (i=0;i<(int)CVAL(buf,smb_wct);i++)
1422 DEBUG(5,("smb_vwv[%d]=%d (0x%X)\n",i,
1423 SVAL(buf,smb_vwv+2*i),SVAL(buf,smb_vwv+2*i)));
1424 bcc = (int)SVAL(buf,smb_vwv+2*(CVAL(buf,smb_wct)));
1425 DEBUG(5,("smb_bcc=%d\n",bcc));
1426 if (DEBUGLEVEL < 10)
1428 for (i=0;i<MIN(bcc,128);i++)
1429 DEBUG(10,("%X ",CVAL(smb_buf(buf),i)));
1433 /*******************************************************************
1434 return the length of an smb packet
1435 ********************************************************************/
1436 int smb_len(char *buf)
1438 return( PVAL(buf,3) | (PVAL(buf,2)<<8) | ((PVAL(buf,1)&1)<<16) );
1441 /*******************************************************************
1442 set the length of an smb packet
1443 ********************************************************************/
1444 void _smb_setlen(char *buf,int len)
1447 buf[1] = (len&0x10000)>>16;
1448 buf[2] = (len&0xFF00)>>8;
1452 /*******************************************************************
1453 set the length and marker of an smb packet
1454 ********************************************************************/
1455 void smb_setlen(char *buf,int len)
1457 _smb_setlen(buf,len);
1465 /*******************************************************************
1466 setup the word count and byte count for a smb message
1467 ********************************************************************/
1468 int set_message(char *buf,int num_words,int num_bytes,BOOL zero)
1471 bzero(buf + smb_size,num_words*2 + num_bytes);
1472 CVAL(buf,smb_wct) = num_words;
1473 SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
1474 smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
1475 return (smb_size + num_words*2 + num_bytes);
1478 /*******************************************************************
1479 return the number of smb words
1480 ********************************************************************/
1481 int smb_numwords(char *buf)
1483 return (CVAL(buf,smb_wct));
1486 /*******************************************************************
1487 return the size of the smb_buf region of a message
1488 ********************************************************************/
1489 int smb_buflen(char *buf)
1491 return(SVAL(buf,smb_vwv0 + smb_numwords(buf)*2));
1494 /*******************************************************************
1495 return a pointer to the smb_buf data area
1496 ********************************************************************/
1497 int smb_buf_ofs(char *buf)
1499 return (smb_size + CVAL(buf,smb_wct)*2);
1502 /*******************************************************************
1503 return a pointer to the smb_buf data area
1504 ********************************************************************/
1505 char *smb_buf(char *buf)
1507 return (buf + smb_buf_ofs(buf));
1510 /*******************************************************************
1511 return the SMB offset into an SMB buffer
1512 ********************************************************************/
1513 int smb_offset(char *p,char *buf)
1515 return(PTR_DIFF(p,buf+4));
1519 /*******************************************************************
1520 skip past some strings in a buffer
1521 ********************************************************************/
1522 char *skip_string(char *buf,int n)
1525 buf += strlen(buf) + 1;
1529 /*******************************************************************
1530 trim the specified elements off the front and back of a string
1531 ********************************************************************/
1532 BOOL trim_string(char *s,char *front,char *back)
1535 while (front && *front && strncmp(s,front,strlen(front)) == 0)
1541 if (!(*p = p[strlen(front)]))
1546 while (back && *back && strlen(s) >= strlen(back) &&
1547 (strncmp(s+strlen(s)-strlen(back),back,strlen(back))==0))
1550 s[strlen(s)-strlen(back)] = 0;
1556 /*******************************************************************
1557 reduce a file name, removing .. elements.
1558 ********************************************************************/
1559 void dos_clean_name(char *s)
1563 DEBUG(3,("dos_clean_name [%s]\n",s));
1565 /* remove any double slashes */
1566 string_sub(s, "\\\\", "\\");
1568 while ((p = strstr(s,"\\..\\")) != NULL)
1575 if ((p=strrchr(s,'\\')) != NULL)
1582 trim_string(s,NULL,"\\..");
1584 string_sub(s, "\\.\\", "\\");
1587 /*******************************************************************
1588 reduce a file name, removing .. elements.
1589 ********************************************************************/
1590 void unix_clean_name(char *s)
1594 DEBUG(3,("unix_clean_name [%s]\n",s));
1596 /* remove any double slashes */
1597 string_sub(s, "//","/");
1599 while ((p = strstr(s,"/../")) != NULL)
1606 if ((p=strrchr(s,'/')) != NULL)
1613 trim_string(s,NULL,"/..");
1617 /*******************************************************************
1618 a wrapper for the normal chdir() function
1619 ********************************************************************/
1620 int ChDir(char *path)
1623 static pstring LastDir="";
1625 if (strcsequal(path,".")) return(0);
1627 if (*path == '/' && strcsequal(LastDir,path)) return(0);
1628 DEBUG(3,("chdir to %s\n",path));
1629 res = sys_chdir(path);
1631 strcpy(LastDir,path);
1636 /*******************************************************************
1637 return the absolute current directory path. A dumb version.
1638 ********************************************************************/
1639 static char *Dumb_GetWd(char *s)
1642 return ((char *)getcwd(s,sizeof(pstring)));
1644 return ((char *)getwd(s));
1649 /* number of list structures for a caching GetWd function. */
1650 #define MAX_GETWDCACHE (50)
1658 } ino_list[MAX_GETWDCACHE];
1660 BOOL use_getwd_cache=True;
1662 /*******************************************************************
1663 return the absolute current directory path
1664 ********************************************************************/
1665 char *GetWd(char *str)
1668 static BOOL getwd_cache_init = False;
1669 struct stat st, st2;
1674 if (!use_getwd_cache)
1675 return(Dumb_GetWd(str));
1677 /* init the cache */
1678 if (!getwd_cache_init)
1680 getwd_cache_init = True;
1681 for (i=0;i<MAX_GETWDCACHE;i++)
1683 string_init(&ino_list[i].text,"");
1684 ino_list[i].valid = False;
1688 /* Get the inode of the current directory, if this doesn't work we're
1691 if (stat(".",&st) == -1)
1693 DEBUG(0,("Very strange, couldn't stat \".\"\n"));
1694 return(Dumb_GetWd(str));
1698 for (i=0; i<MAX_GETWDCACHE; i++)
1699 if (ino_list[i].valid)
1702 /* If we have found an entry with a matching inode and dev number
1703 then find the inode number for the directory in the cached string.
1704 If this agrees with that returned by the stat for the current
1705 directory then all is o.k. (but make sure it is a directory all
1708 if (st.st_ino == ino_list[i].inode &&
1709 st.st_dev == ino_list[i].dev)
1711 if (stat(ino_list[i].text,&st2) == 0)
1713 if (st.st_ino == st2.st_ino &&
1714 st.st_dev == st2.st_dev &&
1715 (st2.st_mode & S_IFMT) == S_IFDIR)
1717 strcpy (str, ino_list[i].text);
1719 /* promote it for future use */
1720 array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i);
1725 /* If the inode is different then something's changed,
1726 scrub the entry and start from scratch. */
1727 ino_list[i].valid = False;
1734 /* We don't have the information to hand so rely on traditional methods.
1735 The very slow getcwd, which spawns a process on some systems, or the
1736 not quite so bad getwd. */
1740 DEBUG(0,("Getwd failed, errno %d\n",errno));
1746 DEBUG(5,("GetWd %s, inode %d, dev %x\n",s,(int)st.st_ino,(int)st.st_dev));
1748 /* add it to the cache */
1749 i = MAX_GETWDCACHE - 1;
1750 string_set(&ino_list[i].text,s);
1751 ino_list[i].dev = st.st_dev;
1752 ino_list[i].inode = st.st_ino;
1753 ino_list[i].valid = True;
1755 /* put it at the top of the list */
1756 array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i);
1763 /*******************************************************************
1764 reduce a file name, removing .. elements and checking that
1765 it is below dir in the heirachy. This uses GetWd() and so must be run
1766 on the system that has the referenced file system.
1768 widelinks are allowed if widelinks is true
1769 ********************************************************************/
1770 BOOL reduce_name(char *s,char *dir,BOOL widelinks)
1772 #ifndef REDUCE_PATHS
1780 BOOL relative = (*s != '/');
1782 *dir2 = *wd = *basename = *newname = 0;
1787 /* can't have a leading .. */
1788 if (strncmp(s,"..",2) == 0 && (s[2]==0 || s[2]=='/'))
1790 DEBUG(3,("Illegal file name? (%s)\n",s));
1796 DEBUG(3,("reduce_name [%s] [%s]\n",s,dir));
1798 /* remove any double slashes */
1799 string_sub(s,"//","/");
1802 p = strrchr(basename,'/');
1809 DEBUG(0,("couldn't getwd for %s %s\n",s,dir));
1813 if (ChDir(dir) != 0)
1815 DEBUG(0,("couldn't chdir to %s\n",dir));
1821 DEBUG(0,("couldn't getwd for %s\n",dir));
1827 if (p && (p != basename))
1830 if (strcmp(p+1,".")==0)
1832 if (strcmp(p+1,"..")==0)
1836 if (ChDir(basename) != 0)
1839 DEBUG(3,("couldn't chdir for %s %s basename=%s\n",s,dir,basename));
1843 if (!GetWd(newname))
1846 DEBUG(2,("couldn't get wd for %s %s\n",s,dir2));
1850 if (p && (p != basename))
1852 strcat(newname,"/");
1853 strcat(newname,p+1);
1857 int l = strlen(dir2);
1858 if (dir2[l-1] == '/')
1861 if (strncmp(newname,dir2,l) != 0)
1864 DEBUG(2,("Bad access attempt? s=%s dir=%s newname=%s l=%d\n",s,dir2,newname,l));
1870 if (newname[l] == '/')
1871 strcpy(s,newname + l + 1);
1873 strcpy(s,newname+l);
1884 DEBUG(3,("reduced to %s\n",s));
1889 /****************************************************************************
1891 ****************************************************************************/
1892 static void expand_one(char *Mask,int len)
1895 while ((p1 = strchr(Mask,'*')) != NULL)
1897 int lfill = (len+1) - strlen(Mask);
1898 int l1= (p1 - Mask);
1901 memset(tmp+l1,'?',lfill);
1902 strcpy(tmp + l1 + lfill,Mask + l1 + 1);
1907 /****************************************************************************
1908 expand a wildcard expression, replacing *s with ?s
1909 ****************************************************************************/
1910 void expand_mask(char *Mask,BOOL doext)
1915 BOOL hasdot = False;
1917 BOOL absolute = (*Mask == '\\');
1919 *mbeg = *mext = *dirpart = *filepart = 0;
1921 /* parse the directory and filename */
1922 if (strchr(Mask,'\\'))
1923 dirname_dos(Mask,dirpart);
1925 filename_dos(Mask,filepart);
1927 strcpy(mbeg,filepart);
1928 if ((p1 = strchr(mbeg,'.')) != NULL)
1938 if (strlen(mbeg) > 8)
1940 strcpy(mext,mbeg + 8);
1946 strcpy(mbeg,"????????");
1947 if ((*mext == 0) && doext && !hasdot)
1950 if (strequal(mbeg,"*") && *mext==0)
1958 strcpy(Mask,dirpart);
1959 if (*dirpart || absolute) strcat(Mask,"\\");
1964 DEBUG(6,("Mask expanded to [%s]\n",Mask));
1968 /****************************************************************************
1969 does a string have any uppercase chars in it?
1970 ****************************************************************************/
1971 BOOL strhasupper(char *s)
1976 if (is_shift_jis (*s)) {
1978 } else if (is_kana (*s)) {
1981 if (isupper(*s)) return(True);
1985 if (isupper(*s)) return(True);
1992 /****************************************************************************
1993 does a string have any lowercase chars in it?
1994 ****************************************************************************/
1995 BOOL strhaslower(char *s)
2000 if (is_shift_jis (*s)) {
2002 } else if (is_kana (*s)) {
2005 if (islower(*s)) return(True);
2009 if (islower(*s)) return(True);
2016 /****************************************************************************
2017 find the number of chars in a string
2018 ****************************************************************************/
2019 int count_chars(char *s,char c)
2032 /****************************************************************************
2034 ****************************************************************************/
2035 void make_dir_struct(char *buf,char *mask,char *fname,unsigned int size,int mode,time_t date)
2042 if ((mode & aDIR) != 0)
2045 memset(buf+1,' ',11);
2046 if ((p = strchr(mask2,'.')) != NULL)
2049 memcpy(buf+1,mask2,MIN(strlen(mask2),8));
2050 memcpy(buf+9,p+1,MIN(strlen(p+1),3));
2054 memcpy(buf+1,mask2,MIN(strlen(mask2),11));
2056 bzero(buf+21,DIR_STRUCT_SIZE-21);
2057 CVAL(buf,21) = mode;
2058 put_dos_date(buf,22,date);
2059 SSVAL(buf,26,size & 0xFFFF);
2060 SSVAL(buf,28,size >> 16);
2061 StrnCpy(buf+30,fname,12);
2062 if (!case_sensitive)
2064 DEBUG(8,("put name [%s] into dir struct\n",buf+30));
2068 /*******************************************************************
2069 close the low 3 fd's and open dev/null in their place
2070 ********************************************************************/
2071 void close_low_fds(void)
2075 close(0); close(1); close(2);
2076 /* try and use up these file descriptors, so silly
2077 library routines writing to stdout etc won't cause havoc */
2079 fd = open("/dev/null",O_RDWR,0);
2080 if (fd < 0) fd = open("/dev/null",O_WRONLY,0);
2082 DEBUG(0,("Can't open /dev/null\n"));
2086 DEBUG(0,("Didn't get file descriptor %d\n",i));
2093 /****************************************************************************
2095 ****************************************************************************/
2096 int write_socket(int fd,char *buf,int len)
2102 DEBUG(6,("write_socket(%d,%d)\n",fd,len));
2103 ret = write_data(fd,buf,len);
2105 DEBUG(6,("write_socket(%d,%d) wrote %d\n",fd,len,ret));
2109 /****************************************************************************
2111 ****************************************************************************/
2112 int read_udp_socket(int fd,char *buf,int len)
2115 struct sockaddr sock;
2118 socklen = sizeof(sock);
2119 bzero((char *)&sock,socklen);
2120 bzero((char *)&lastip,sizeof(lastip));
2121 ret = recvfrom(fd,buf,len,0,&sock,&socklen);
2124 DEBUG(2,("read socket failed. ERRNO=%d\n",errno));
2128 lastip = *(struct in_addr *) &sock.sa_data[2];
2129 lastport = ntohs(((struct sockaddr_in *)&sock)->sin_port);
2134 /****************************************************************************
2135 Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
2137 if SYSV use O_NDELAY
2139 ****************************************************************************/
2140 int set_blocking(int fd, BOOL set)
2144 #define FLAG_TO_SET O_NONBLOCK
2147 #define FLAG_TO_SET O_NDELAY
2149 #define FLAG_TO_SET FNDELAY
2153 if((val = fcntl(fd, F_GETFL, 0))==-1)
2155 if(set) /* Turn blocking on - ie. clear nonblock flag */
2156 val &= ~FLAG_TO_SET;
2159 return fcntl( fd, F_SETFL, val);
2164 /****************************************************************************
2165 Calculate the difference in timeout values. Return 1 if val1 > val2,
2166 0 if val1 == val2, -1 if val1 < val2. Stores result in retval. retval
2167 may be == val1 or val2
2168 ****************************************************************************/
2169 static int tval_sub( struct timeval *retval, struct timeval *val1, struct timeval *val2)
2171 int usecdiff = val1->tv_usec - val2->tv_usec;
2172 int secdiff = val1->tv_sec - val2->tv_sec;
2174 usecdiff = 1000000 + usecdiff;
2177 retval->tv_sec = secdiff;
2178 retval->tv_usec = usecdiff;
2183 return (usecdiff < 0 ) ? -1 : ((usecdiff > 0 ) ? 1 : 0);
2186 /****************************************************************************
2187 read data from a device with a timout in msec.
2188 mincount = if timeout, minimum to read before returning
2189 maxcount = number to be read.
2190 ****************************************************************************/
2191 int read_with_timeout(int fd,char *buf,int mincnt,int maxcnt,long time_out,BOOL exact)
2197 struct timeval timeout, tval1, tval2, tvaldiff;
2198 int error_limit = 5;
2200 /* just checking .... */
2201 if (maxcnt <= 0) return(0);
2204 time_out = DEFAULT_PIPE_TIMEOUT;
2208 if (mincnt == 0) mincnt = maxcnt;
2210 while (nread < mincnt)
2212 readret = read(fd, buf + nread, maxcnt - nread);
2213 if (readret <= 0) return(nread);
2219 /* Non blocking read */
2221 set_blocking(fd, False);
2222 nread = read_data(fd, buf, mincnt);
2224 nread += read(fd,buf+nread,maxcnt-nread);
2225 if(nread == -1 && errno == EWOULDBLOCK)
2227 set_blocking(fd,True);
2231 /* Most difficult - timeout read */
2232 /* If this is ever called on a disk file and
2233 mincnt is greater then the filesize then
2234 system performance will suffer severely as
2235 select always return true on disk files */
2237 /* Set initial timeout */
2238 timeout.tv_sec = time_out / 1000;
2239 timeout.tv_usec = 1000 * (time_out % 1000);
2241 /* As most UNIXes don't modify the value of timeout
2242 when they return from select we need to get the timeofday (in usec)
2243 now, and also after the select returns so we know
2244 how much time has elapsed */
2247 GetTimeOfDay( &tval1);
2248 nread = 0; /* Number of bytes we have read */
2255 selrtn = sys_select(&fds,&timeout);
2257 /* Check if error */
2263 /* Did we timeout ? */
2265 if (nread < mincnt) return -1;
2269 readret = read(fd, buf+nread, maxcnt-nread);
2270 if (readret == 0 && nread < mincnt) {
2271 /* error_limit should not really be needed, but some systems
2272 do strange things ... I don't want to just continue
2273 indefinately in case we get an infinite loop */
2274 if (error_limit--) continue;
2279 /* force a particular error number for
2281 DEBUG(5,("read gave error %s\n",strerror(errno)));
2288 /* If we have read more than mincnt then return */
2289 if (nread >= mincnt)
2292 /* We need to do another select - but first reduce the
2293 time_out by the amount of time already elapsed - if
2294 this is less than zero then return */
2296 GetTimeOfDay(&tval2);
2297 (void)tval_sub( &tvaldiff, &tval2, &tval1);
2299 if (tval_sub(&timeout, &timeout, &tvaldiff) <= 0)
2300 break; /* We timed out */
2303 /* Save the time of day as we need to do the select
2304 again (saves a system call) */
2308 /* Return the number we got */
2312 /****************************************************************************
2313 read data from the client. Maxtime is in milliseconds
2314 ****************************************************************************/
2315 int read_max_udp(int fd,char *buffer,int bufsize,int maxtime)
2320 struct timeval timeout;
2325 timeout.tv_sec = maxtime / 1000;
2326 timeout.tv_usec = (maxtime % 1000) * 1000;
2328 selrtn = sys_select(&fds,maxtime>0?&timeout:NULL);
2330 if (!FD_ISSET(fd,&fds))
2333 nread = read_udp_socket(fd, buffer, bufsize);
2335 /* return the number got */
2339 /*******************************************************************
2340 find the difference in milliseconds between two struct timeval
2342 ********************************************************************/
2343 int TvalDiff(struct timeval *tvalold,struct timeval *tvalnew)
2345 return((tvalnew->tv_sec - tvalold->tv_sec)*1000 +
2346 ((int)tvalnew->tv_usec - (int)tvalold->tv_usec)/1000);
2349 /****************************************************************************
2350 send a keepalive packet (rfc1002)
2351 ****************************************************************************/
2352 BOOL send_keepalive(int client)
2354 unsigned char buf[4];
2357 buf[1] = buf[2] = buf[3] = 0;
2359 return(write_data(client,(char *)buf,4) == 4);
2364 /****************************************************************************
2365 read data from the client, reading exactly N bytes.
2366 ****************************************************************************/
2367 int read_data(int fd,char *buffer,int N)
2374 ret = read(fd,buffer + total,N - total);
2376 /* this is for portability */
2388 /****************************************************************************
2390 ****************************************************************************/
2391 int write_data(int fd,char *buffer,int N)
2398 ret = write(fd,buffer + total,N - total);
2409 /* variables used by the read prediction module */
2414 int rp_predict_fd = -1;
2415 int rp_predict_offset = 0;
2416 int rp_predict_length = 0;
2419 char *rp_buffer = NULL;
2420 BOOL predict_skip=False;
2421 time_t smb_last_time=(time_t)0;
2423 /****************************************************************************
2424 handle read prediction on a file
2425 ****************************************************************************/
2426 int read_predict(int fd,int offset,char *buf,char **ptr,int num)
2429 int possible = rp_length - (offset - rp_offset);
2431 possible = MIN(possible,num);
2433 /* give data if possible */
2435 offset >= rp_offset &&
2437 smb_last_time-rp_time < rp_timeout)
2441 memcpy(buf,rp_buffer + (offset-rp_offset),possible);
2443 *ptr = rp_buffer + (offset-rp_offset);
2444 DEBUG(5,("read-prediction gave %d bytes of %d\n",ret,num));
2448 predict_skip = True;
2450 predict_skip = False;
2452 /* prepare the next prediction */
2454 rp_predict_offset = offset + num;
2455 rp_predict_length = num;
2458 if (ret < 0) ret = 0;
2463 /****************************************************************************
2465 ****************************************************************************/
2466 void do_read_prediction()
2468 if (predict_skip) return;
2470 if (rp_predict_fd == -1)
2473 rp_fd = rp_predict_fd;
2474 rp_offset = rp_predict_offset;
2479 rp_predict_length = MIN(rp_predict_length,2*ReadSize);
2480 rp_predict_length = MAX(rp_predict_length,1024);
2481 rp_offset = (rp_offset/1024)*1024;
2482 rp_predict_length = (rp_predict_length/1024)*1024;
2484 if (rp_predict_length > rp_alloced)
2486 rp_buffer = Realloc(rp_buffer,rp_predict_length);
2487 rp_alloced = rp_predict_length;
2490 DEBUG(0,("can't allocate read-prediction buffer\n"));
2498 if (lseek(rp_fd,rp_offset,SEEK_SET) != rp_offset) {
2504 rp_length = read(rp_fd,rp_buffer,rp_predict_length);
2505 rp_time = time(NULL);
2510 /****************************************************************************
2511 invalidate read-prediction on a fd
2512 ****************************************************************************/
2513 void invalidate_read_prediction(int fd)
2517 if (rp_predict_fd == fd)
2522 /****************************************************************************
2523 transfer some data between two fd's
2524 ****************************************************************************/
2525 int transfer_file(int infd,int outfd,int n,char *header,int headlen,int align)
2527 static char *buf=NULL;
2529 static int size = 0;
2532 DEBUG(4,("transfer_file %d (head=%d) called\n",n,headlen));
2534 if ((size < ReadSize) && buf) {
2539 size = MAX(ReadSize,1024);
2541 while (!buf && size>0) {
2542 buf = (char *)Realloc(buf,size+8);
2543 if (!buf) size /= 2;
2546 DEBUG(0,("Can't allocate transfer buffer!\n"));
2550 abuf = buf + (align%8);
2557 int s = MIN(n,size);
2562 if (header && (headlen >= MIN(s,1024))) {
2572 if (header && headlen > 0)
2574 ret = MIN(headlen,size);
2575 memcpy(buf1,header,ret);
2578 if (headlen <= 0) header = NULL;
2582 ret += read(infd,buf1+ret,s-ret);
2586 ret2 = (outfd>=0?write_data(outfd,buf1,ret):ret);
2587 if (ret2 > 0) total += ret2;
2588 /* if we can't write then dump excess data */
2590 transfer_file(infd,-1,n-(ret+headlen),NULL,0,0);
2592 if (ret <= 0 || ret2 != ret)
2600 /****************************************************************************
2601 read 4 bytes of a smb packet and return the smb length of the packet
2602 possibly store the result in the buffer
2603 ****************************************************************************/
2604 int read_smb_length(int fd,char *inbuf,int timeout)
2608 int len=0, msg_type;
2619 ok = (read_with_timeout(fd,buffer,4,4,timeout,False) == 4);
2621 ok = (read_data(fd,buffer,4) == 4);
2627 DEBUG(10,("select timeout (%d)\n", timeout));
2632 DEBUG(6,("couldn't read from client\n"));
2637 len = smb_len(buffer);
2638 msg_type = CVAL(buffer,0);
2640 if (msg_type == 0x85)
2642 DEBUG(5,( "Got keepalive packet\n"));
2647 DEBUG(10,("got smb length of %d\n",len));
2654 /****************************************************************************
2655 read an smb from a fd and return it's length
2656 The timeout is in milli seconds
2657 ****************************************************************************/
2658 BOOL receive_smb(int fd,char *buffer,int timeout)
2663 bzero(buffer,smb_size + 100);
2665 len = read_smb_length(fd,buffer,timeout);
2669 if (len > BUFFER_SIZE)
2671 DEBUG(0,("Invalid packet length! (%d bytes)\n",len));
2672 if (len > BUFFER_SIZE + (SAFETY_MARGIN/2))
2676 ok = (read_data(fd,buffer+4,len) == len);
2688 /****************************************************************************
2690 ****************************************************************************/
2691 BOOL send_smb(int fd,char *buffer)
2695 len = smb_len(buffer) + 4;
2697 while (nwritten < len)
2699 ret = write_socket(fd,buffer+nwritten,len - nwritten);
2702 DEBUG(0,("Error writing %d bytes to client. %d. Exiting\n",len,ret));
2714 /****************************************************************************
2715 find a pointer to a netbios name
2716 ****************************************************************************/
2717 char *name_ptr(char *buf,int ofs)
2719 unsigned char c = *(unsigned char *)(buf+ofs);
2721 if ((c & 0xC0) == 0xC0)
2725 memcpy(p,buf+ofs,2);
2728 DEBUG(5,("name ptr to pos %d from %d is %s\n",l,ofs,buf+l));
2735 /****************************************************************************
2736 extract a netbios name from a buf
2737 ****************************************************************************/
2738 int name_extract(char *buf,int ofs,char *name)
2740 char *p = name_ptr(buf,ofs);
2741 int d = PTR_DIFF(p,buf+ofs);
2743 if (d < -50 || d > 50) return(0);
2744 return(name_interpret(p,name));
2748 /****************************************************************************
2749 return the total storage length of a mangled name
2750 ****************************************************************************/
2751 int name_len(char *s)
2754 unsigned char c = *(unsigned char *)s;
2755 if ((c & 0xC0) == 0xC0)
2757 while (*s) s += (*s)+1;
2758 return(PTR_DIFF(s,s0)+1);
2761 /****************************************************************************
2762 send a single packet to a port on another machine
2763 ****************************************************************************/
2764 BOOL send_one_packet(char *buf,int len,struct in_addr ip,int port,int type)
2768 struct sockaddr_in sock_out;
2773 /* create a socket to write to */
2774 out_fd = socket(AF_INET, type, 0);
2777 DEBUG(0,("socket failed"));
2781 /* set the address and port */
2782 bzero((char *)&sock_out,sizeof(sock_out));
2783 putip((char *)&sock_out.sin_addr,(char *)&ip);
2784 sock_out.sin_port = htons( port );
2785 sock_out.sin_family = AF_INET;
2788 DEBUG(3,("sending a packet of len %d to (%s) on port %d of type %s\n",
2789 len,inet_ntoa(ip),port,type==SOCK_DGRAM?"DGRAM":"STREAM"));
2792 ret = (sendto(out_fd,buf,len,0,(struct sockaddr *)&sock_out,sizeof(sock_out)) >= 0);
2795 DEBUG(0,("Packet send to %s(%d) failed ERRNO=%d\n",
2796 inet_ntoa(ip),port,errno));
2802 /*******************************************************************
2803 sleep for a specified number of milliseconds
2804 ********************************************************************/
2808 struct timeval tval,t1,t2;
2815 tval.tv_sec = (t-tdiff)/1000;
2816 tval.tv_usec = 1000*((t-tdiff)%1000);
2820 sys_select(&fds,&tval);
2823 tdiff = TvalDiff(&t1,&t2);
2827 /****************************************************************************
2828 check if a string is part of a list
2829 ****************************************************************************/
2830 BOOL in_list(char *s,char *list,BOOL casesensitive)
2835 if (!list) return(False);
2837 while (next_token(&p,tok,LIST_SEP))
2839 if (casesensitive) {
2840 if (strcmp(tok,s) == 0)
2843 if (StrCaseCmp(tok,s) == 0)
2850 /* this is used to prevent lots of mallocs of size 1 */
2851 static char *null_string = NULL;
2853 /****************************************************************************
2854 set a string value, allocing the space for the string
2855 ****************************************************************************/
2856 BOOL string_init(char **dest,char *src)
2867 null_string = (char *)malloc(1);
2870 *dest = null_string;
2874 *dest = (char *)malloc(l+1);
2880 /****************************************************************************
2882 ****************************************************************************/
2883 void string_free(char **s)
2885 if (!s || !(*s)) return;
2886 if (*s == null_string)
2892 /****************************************************************************
2893 set a string value, allocing the space for the string, and deallocating any
2895 ****************************************************************************/
2896 BOOL string_set(char **dest,char *src)
2900 return(string_init(dest,src));
2903 /****************************************************************************
2904 substitute a string for a pattern in another string. Make sure there is
2907 This routine looks for pattern in s and replaces it with
2908 insert. It may do multiple replacements.
2910 return True if a substitution was done.
2911 ****************************************************************************/
2912 BOOL string_sub(char *s,char *pattern,char *insert)
2918 if (!insert || !pattern || !s) return(False);
2921 lp = strlen(pattern);
2922 li = strlen(insert);
2924 if (!*pattern) return(False);
2926 while (lp <= ls && (p = strstr(s,pattern)))
2929 memmove(p+li,p+lp,ls + 1 - (PTR_DIFF(p,s) + lp));
2930 memcpy(p,insert,li);
2939 /*********************************************************
2940 * Recursive routine that is called by mask_match.
2941 * Does the actual matching.
2942 *********************************************************/
2943 BOOL do_match(char *str, char *regexp, int case_sig)
2947 for( p = regexp; *p && *str; ) {
2954 /* Look for a character matching
2955 the one after the '*' */
2958 return True; /* Automatic match */
2960 while(*str && (case_sig ? (*p != *str) : (toupper(*p)!=toupper(*str))))
2962 if(do_match(str,p,case_sig))
2976 if(toupper(*str) != toupper(*p))
2986 if (!*p && str[0] == '.' && str[1] == 0)
2989 if (!*str && *p == '?')
2991 while (*p == '?') p++;
2995 if(!*str && (*p == '*' && p[1] == '\0'))
3001 /*********************************************************
3002 * Routine to match a given string with a regexp - uses
3003 * simplified regexp that takes * and ? only. Case can be
3004 * significant or not.
3005 *********************************************************/
3006 BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
3010 fstring ebase,eext,sbase,sext;
3014 /* Make local copies of str and regexp */
3015 StrnCpy(p1,regexp,sizeof(pstring)-1);
3016 StrnCpy(p2,str,sizeof(pstring)-1);
3018 if (!strchr(p2,'.')) {
3023 if (!strchr(p1,'.')) {
3031 string_sub(p1,"*.*","*");
3032 string_sub(p1,".*","*");
3036 /* Remove any *? and ** as they are meaningless */
3037 for(p = p1; *p; p++)
3038 while( *p == '*' && (p[1] == '?' ||p[1] == '*'))
3039 (void)strcpy( &p[1], &p[2]);
3041 if (strequal(p1,"*")) return(True);
3043 DEBUG(5,("mask_match str=<%s> regexp=<%s>, case_sig = %d\n", p2, p1, case_sig));
3049 if ((p=strrchr(p1,'.'))) {
3058 if (!strequal(p2,".") && !strequal(p2,"..") && (p=strrchr(p2,'.'))) {
3068 matched = do_match(sbase,ebase,case_sig) &&
3069 (trans2 || do_match(sext,eext,case_sig));
3071 DEBUG(5,("mask_match returning %d\n", matched));
3078 /****************************************************************************
3079 become a daemon, discarding the controlling terminal
3080 ****************************************************************************/
3081 void become_daemon(void)
3083 #ifndef NO_FORK_DEBUG
3087 /* detach from the terminal */
3093 int i = open("/dev/tty", O_RDWR);
3096 ioctl(i, (int) TIOCNOTTY, (char *)0);
3105 /****************************************************************************
3106 calculate the default netmask for an address
3107 ****************************************************************************/
3108 static void default_netmask(struct in_addr *inm, struct in_addr *iad)
3110 unsigned long ad = ntohl(iad->s_addr);
3113 ** Guess a netmask based on the class of the IP address given.
3115 if ( (ad & 0x80000000) == 0 ) {
3116 /* class A address */
3118 } else if ( (ad & 0xC0000000) == 0x80000000 ) {
3119 /* class B address */
3121 } else if ( (ad & 0xE0000000) == 0xC0000000 ) {
3122 /* class C address */
3125 /* class D or E; netmask doesn't make much sense - guess 4 bits */
3128 inm->s_addr = htonl(nm);
3131 /****************************************************************************
3132 get the broadcast address for our address
3133 (troyer@saifr00.ateng.az.honeywell.com)
3134 ****************************************************************************/
3135 void get_broadcast(struct in_addr *if_ipaddr,
3136 struct in_addr *if_bcast,
3137 struct in_addr *if_nmask)
3140 #ifndef NO_GET_BROADCAST
3141 int sock = -1; /* AF_INET raw socket desc */
3143 struct ifreq *ifr=NULL;
3146 #if defined(EVEREST)
3149 struct ifreq *ifreqs;
3150 #elif defined(USE_IFREQ)
3152 struct strioctl strioctl;
3159 /* get a default netmask and broadcast */
3160 default_netmask(if_nmask, if_ipaddr);
3162 #ifndef NO_GET_BROADCAST
3163 /* Create a socket to the INET kernel. */
3165 if ((sock = socket(AF_INET, SOCK_RAW, PF_INET )) < 0)
3167 if ((sock = socket(AF_INET, SOCK_DGRAM, 0 )) < 0)
3170 DEBUG(0,( "Unable to open socket to get broadcast address\n"));
3174 /* Get a list of the configured interfaces */
3176 /* This is part of SCO Openserver 5: The ioctls are no longer part
3177 if the lower level STREAMS interface glue. They are now real
3180 if (ioctl(sock, SIOCGIFANUM, &n_interfaces) < 0) {
3181 DEBUG(0,( "SIOCGIFANUM: %s\n", strerror(errno)));
3183 DEBUG(0,( "number of interfaces returned is: %d\n", n_interfaces));
3185 ifc.ifc_len = sizeof(struct ifreq) * n_interfaces;
3186 ifc.ifc_buf = (caddr_t) alloca(ifc.ifc_len);
3188 if (ioctl(sock, SIOCGIFCONF, &ifc) < 0)
3189 DEBUG(0, ( "SIOCGIFCONF: %s\n", strerror(errno)));
3193 for (i = 0; i < n_interfaces; ++i) {
3194 if (if_ipaddr->s_addr ==
3195 ((struct sockaddr_in *) &ifr[i].ifr_addr)->sin_addr.s_addr) {
3202 #elif defined(USE_IFREQ)
3203 ifc = (struct ifconf *)buff;
3204 ifc->ifc_len = BUFSIZ - sizeof(struct ifconf);
3205 strioctl.ic_cmd = SIOCGIFCONF;
3206 strioctl.ic_dp = (char *)ifc;
3207 strioctl.ic_len = sizeof(buff);
3208 if (ioctl(sock, I_STR, &strioctl) < 0) {
3209 DEBUG(0,( "I_STR/SIOCGIFCONF: %s\n", strerror(errno)));
3211 ifr = (struct ifreq *)ifc->ifc_req;
3213 /* Loop through interfaces, looking for given IP address */
3214 for (i = ifc->ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) {
3215 if (if_ipaddr->s_addr ==
3216 (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr) {
3222 #elif defined(__FreeBSD__) || defined(NETBSD)
3223 ifc.ifc_len = sizeof(buff);
3225 if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) {
3226 DEBUG(0,("SIOCGIFCONF: %s\n", strerror(errno)));
3229 /* Loop through interfaces, looking for given IP address */
3232 if (if_ipaddr->s_addr ==
3233 (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr) {
3237 i -= ifr->ifr_addr.sa_len + IFNAMSIZ;
3238 ifr = (struct ifreq*) ((char*) ifr + ifr->ifr_addr.sa_len + IFNAMSIZ);
3242 ifc.ifc_len = sizeof(buff);
3244 if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) {
3245 DEBUG(0,("SIOCGIFCONF: %s\n", strerror(errno)));
3249 /* Loop through interfaces, looking for given IP address */
3250 for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) {
3252 if (ioctl(sock, SIOCGIFADDR, ifr) < 0) break;
3254 if (if_ipaddr->s_addr ==
3255 (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr) {
3264 DEBUG(0,("No interface found for address %s\n", inet_ntoa(*if_ipaddr)));
3266 /* Get the netmask address from the kernel */
3270 strioctl.ic_cmd = SIOCGIFNETMASK;
3271 strioctl.ic_dp = (char *)&ifreq;
3272 strioctl.ic_len = sizeof(struct ifreq);
3273 if (ioctl(sock, I_STR, &strioctl) < 0)
3274 DEBUG(0,("Failed I_STR/SIOCGIFNETMASK: %s\n", strerror(errno)));
3276 *if_nmask = ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr;
3278 if (ioctl(sock, SIOCGIFNETMASK, ifr) < 0)
3279 DEBUG(0,("SIOCGIFNETMASK failed\n"));
3281 *if_nmask = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr;
3284 DEBUG(2,("Netmask for %s = %s\n", ifr->ifr_name,
3285 inet_ntoa(*if_nmask)));
3293 /* sanity check on the netmask */
3295 unsigned long nm = ntohl(if_nmask->s_addr);
3296 if ((nm >> 24) != 0xFF) {
3297 DEBUG(0,("Impossible netmask %s - using defaults\n",inet_ntoa(*if_nmask)));
3298 default_netmask(if_nmask, if_ipaddr);
3302 /* derive the broadcast assuming a 1's broadcast, as this is what
3303 all MS operating systems do, we have to comply even if the unix
3304 box is setup differently */
3306 unsigned long ad = ntohl(if_ipaddr->s_addr);
3307 unsigned long nm = ntohl(if_nmask->s_addr);
3308 unsigned long bc = (ad & nm) | (0xffffffff & ~nm);
3309 if_bcast->s_addr = htonl(bc);
3312 DEBUG(2,("Derived broadcast address %s\n", inet_ntoa(*if_bcast)));
3313 } /* get_broadcast */
3316 /****************************************************************************
3317 put up a yes/no prompt
3318 ****************************************************************************/
3324 if (!fgets(ans,sizeof(ans)-1,stdin))
3327 if (*ans == 'y' || *ans == 'Y')
3333 /****************************************************************************
3334 read a line from a file with possible \ continuation chars.
3335 Blanks at the start or end of a line are stripped.
3336 The string will be allocated if s2 is NULL
3337 ****************************************************************************/
3338 char *fgets_slash(char *s2,int maxlen,FILE *f)
3343 BOOL start_of_line = True;
3350 maxlen = MIN(maxlen,8);
3351 s = (char *)Realloc(s,maxlen);
3354 if (!s || maxlen < 2) return(NULL);
3358 while (len < maxlen-1)
3366 while (len > 0 && s[len-1] == ' ')
3370 if (len > 0 && s[len-1] == '\\')
3373 start_of_line = True;
3378 if (len <= 0 && !s2)
3380 return(len>0?s:NULL);
3385 start_of_line = False;
3389 if (!s2 && len > maxlen-3)
3392 s = (char *)Realloc(s,maxlen);
3393 if (!s) return(NULL);
3401 /****************************************************************************
3402 set the length of a file from a filedescriptor.
3403 Returns 0 on success, -1 on failure.
3404 ****************************************************************************/
3405 int set_filelen(int fd, long len)
3407 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
3408 extend a file with ftruncate. Provide alternate implementation
3411 #if FTRUNCATE_CAN_EXTEND
3412 return ftruncate(fd, len);
3416 long currpos = lseek(fd, 0L, SEEK_CUR);
3420 /* Do an fstat to see if the file is longer than
3421 the requested size (call ftruncate),
3422 or shorter, in which case seek to len - 1 and write 1
3424 if(fstat(fd, &st)<0)
3428 if (S_ISFIFO(st.st_mode)) return 0;
3431 if(st.st_size == len)
3433 if(st.st_size > len)
3434 return ftruncate(fd, len);
3436 if(lseek(fd, len-1, SEEK_SET) != len -1)
3438 if(write(fd, &c, 1)!=1)
3440 /* Seek to where we were */
3441 lseek(fd, currpos, SEEK_SET);
3447 /****************************************************************************
3448 return the byte checksum of some data
3449 ****************************************************************************/
3450 int byte_checksum(char *buf,int len)
3452 unsigned char *p = (unsigned char *)buf;
3462 /****************************************************************************
3463 this is a version of setbuffer() for those machines that only have setvbuf
3464 ****************************************************************************/
3465 void setbuffer(FILE *f,char *buf,int bufsize)
3467 setvbuf(f,buf,_IOFBF,bufsize);
3472 /****************************************************************************
3473 parse out a directory name from a path name. Assumes dos style filenames.
3474 ****************************************************************************/
3475 char *dirname_dos(char *path,char *buf)
3477 char *p = strrchr(path,'\\');
3492 /****************************************************************************
3493 parse out a filename from a path name. Assumes dos style filenames.
3494 ****************************************************************************/
3495 static char *filename_dos(char *path,char *buf)
3497 char *p = strrchr(path,'\\');
3509 /****************************************************************************
3510 expand a pointer to be a particular size
3511 ****************************************************************************/
3512 void *Realloc(void *p,int size)
3516 ret = (void *)malloc(size);
3518 ret = (void *)realloc(p,size);
3521 DEBUG(0,("Memory allocation error: failed to expand to %d bytes\n",size));
3526 /****************************************************************************
3527 set the time on a file
3528 ****************************************************************************/
3529 BOOL set_filetime(char *fname,time_t mtime)
3531 struct utimbuf times;
3533 if (null_mtime(mtime)) return(True);
3535 times.modtime = times.actime = mtime;
3537 if (sys_utime(fname,×)) {
3538 DEBUG(4,("set_filetime(%s) failed: %s\n",fname,strerror(errno)));
3546 /****************************************************************************
3548 ****************************************************************************/
3549 char *strdup(char *s)
3552 if (!s) return(NULL);
3553 ret = (char *)malloc(strlen(s)+1);
3554 if (!ret) return(NULL);
3561 /****************************************************************************
3562 Signal handler for SIGPIPE (write on a disconnected socket)
3563 ****************************************************************************/
3566 DEBUG(0,("Probably got SIGPIPE\nExiting\n"));
3571 #ifdef REPLACE_STRLEN
3572 /****************************************************************************
3573 a replacement strlen() that returns int for solaris
3574 ****************************************************************************/
3585 /****************************************************************************
3586 return a time at the start of the current month
3587 ****************************************************************************/
3588 time_t start_of_month(void)
3590 time_t t = time(NULL);
3604 /*******************************************************************
3605 check for a sane unix date
3606 ********************************************************************/
3607 BOOL sane_unix_date(time_t unixdate)
3610 time_t t_today = time(NULL);
3612 t = *(LocalTime(&unixdate,LOCAL_TO_GMT));
3613 today = *(LocalTime(&t_today,LOCAL_TO_GMT));
3618 if (t.tm_year > today.tm_year)
3621 if (t.tm_year == today.tm_year &&
3622 t.tm_mon > today.tm_mon)
3626 if (t.tm_year == today.tm_year &&
3627 t.tm_mon == today.tm_mon &&
3628 t.tm_mday > (today.tm_mday+1))
3637 /*******************************************************************
3638 ftruncate for operating systems that don't have it
3639 ********************************************************************/
3640 int ftruncate(int f,long l)
3647 fl.l_type = F_WRLCK;
3648 return fcntl(f, F_FREESP, &fl);
3654 /****************************************************************************
3655 get my own name and IP
3656 ****************************************************************************/
3657 BOOL get_myname(char *myname,struct in_addr *ip)
3664 /* get my host name */
3665 if (gethostname(hostname, MAXHOSTNAMELEN) == -1)
3667 DEBUG(0,("gethostname failed\n"));
3672 if ((hp = Get_Hostbyname(hostname)) == 0)
3674 DEBUG(0,( "Get_Hostbyname: Unknown host %s.\n",hostname));
3680 /* split off any parts after an initial . */
3681 char *p = strchr(hostname,'.');
3684 strcpy(myname,hostname);
3688 putip((char *)ip,(char *)hp->h_addr);
3694 /****************************************************************************
3695 true if two IP addresses are equal
3696 ****************************************************************************/
3697 BOOL ip_equal(struct in_addr ip1,struct in_addr ip2)
3699 unsigned long a1,a2;
3700 a1 = ntohl(ip1.s_addr);
3701 a2 = ntohl(ip2.s_addr);
3706 /****************************************************************************
3707 open a socket of the specified type, port and address for incoming data
3708 ****************************************************************************/
3709 int open_socket_in(int type, int port, int dlevel)
3712 struct sockaddr_in sock;
3716 /* get my host name */
3717 #ifdef MAXHOSTNAMELEN
3718 if (gethostname(host_name, MAXHOSTNAMELEN) == -1)
3720 if (gethostname(host_name, sizeof(host_name)) == -1)
3722 { DEBUG(0,("gethostname failed\n")); return -1; }
3725 if ((hp = Get_Hostbyname(host_name)) == 0)
3727 DEBUG(0,( "Get_Hostbyname: Unknown host. %s\n",host_name));
3731 bzero((char *)&sock,sizeof(sock));
3732 memcpy((char *)&sock.sin_addr,(char *)hp->h_addr, hp->h_length);
3733 #if defined(__FreeBSD__) || defined(NETBSD) /* XXX not the right ifdef */
3734 sock.sin_len = sizeof(sock);
3736 sock.sin_port = htons( port );
3737 sock.sin_family = hp->h_addrtype;
3738 sock.sin_addr.s_addr = INADDR_ANY;
3739 res = socket(hp->h_addrtype, type, 0);
3741 { DEBUG(0,("socket failed\n")); return -1; }
3745 setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
3748 /* now we've got a socket - we need to bind it */
3749 if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) < 0)
3752 if (port == 139 || port == 137)
3753 DEBUG(dlevel,("bind failed on port %d (%s)\n",
3754 port,strerror(errno)));
3757 if (dlevel > 0 && port < 1000)
3760 if (port >= 1000 && port < 9000)
3761 return(open_socket_in(type,port+1,dlevel));
3766 DEBUG(3,("bind succeeded on port %d\n",port));
3772 /****************************************************************************
3773 create an outgoing socket
3774 **************************************************************************/
3775 int open_socket_out(int type, struct in_addr *addr, int port )
3777 struct sockaddr_in sock_out;
3780 /* create a socket to write to */
3781 res = socket(PF_INET, type, 0);
3783 { DEBUG(0,("socket error\n")); return -1; }
3785 if (type != SOCK_STREAM) return(res);
3787 bzero((char *)&sock_out,sizeof(sock_out));
3788 putip((char *)&sock_out.sin_addr,(char *)addr);
3790 sock_out.sin_port = htons( port );
3791 sock_out.sin_family = PF_INET;
3793 DEBUG(3,("Connecting to %s at port %d\n",inet_ntoa(*addr),port));
3795 /* and connect it to the destination */
3796 if (connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out))<0) {
3797 DEBUG(0,("connect error: %s\n",strerror(errno)));
3806 /****************************************************************************
3807 interpret a protocol description string, with a default
3808 ****************************************************************************/
3809 int interpret_protocol(char *str,int def)
3811 if (strequal(str,"NT1"))
3812 return(PROTOCOL_NT1);
3813 if (strequal(str,"LANMAN2"))
3814 return(PROTOCOL_LANMAN2);
3815 if (strequal(str,"LANMAN1"))
3816 return(PROTOCOL_LANMAN1);
3817 if (strequal(str,"CORE"))
3818 return(PROTOCOL_CORE);
3819 if (strequal(str,"COREPLUS"))
3820 return(PROTOCOL_COREPLUS);
3821 if (strequal(str,"CORE+"))
3822 return(PROTOCOL_COREPLUS);
3824 DEBUG(0,("Unrecognised protocol level %s\n",str));
3829 /****************************************************************************
3830 interpret a security level
3831 ****************************************************************************/
3832 int interpret_security(char *str,int def)
3834 if (strequal(str,"SERVER"))
3836 if (strequal(str,"USER"))
3838 if (strequal(str,"SHARE"))
3841 DEBUG(0,("Unrecognised security level %s\n",str));
3847 /****************************************************************************
3848 interpret an internet address or name into an IP address in 4 byte form
3849 ****************************************************************************/
3850 unsigned long interpret_addr(char *str)
3855 if (strcmp(str,"0.0.0.0") == 0) return(0);
3856 if (strcmp(str,"255.255.255.255") == 0) return(0xFFFFFFFF);
3858 /* if it's in the form of an IP address then get the lib to interpret it */
3859 if (isdigit(str[0])) {
3860 res = inet_addr(str);
3862 /* otherwise assume it's a network name of some sort and use Get_Hostbyname */
3863 if ((hp = Get_Hostbyname(str)) == 0) {
3864 DEBUG(3,("Get_Hostbyname: Unknown host. %s\n",str));
3867 putip((char *)&res,(char *)hp->h_addr);
3870 if (res == (unsigned long)-1) return(0);
3875 /*******************************************************************
3876 a convenient addition to interpret_addr()
3877 ******************************************************************/
3878 struct in_addr *interpret_addr2(char *str)
3880 static struct in_addr ret;
3881 unsigned long a = interpret_addr(str);
3882 putip((char *)&ret,(char *)&a);
3886 /*******************************************************************
3887 check if an IP is the 0.0.0.0
3888 ******************************************************************/
3889 BOOL zero_ip(struct in_addr ip)
3892 putip((char *)&a,(char *)&ip);
3896 #define TIME_FIXUP_CONSTANT (369.0*365.25*24*60*60-(3.0*24*60*60+6.0*60*60))
3898 /****************************************************************************
3899 interpret an 8 byte "filetime" structure to a time_t
3900 It's originally in "100ns units since jan 1st 1601"
3902 It appears to be kludge-GMT (at least for file listings). This means
3903 its the GMT you get by taking a localtime and adding the
3904 serverzone. This is NOT the same as GMT in some cases. This routine
3905 converts this to real GMT.
3906 ****************************************************************************/
3907 time_t interpret_long_date(char *p)
3915 if (thigh == 0) return(0);
3917 d = ((double)thigh)*4.0*(double)(1<<30);
3918 d += (tlow&0xFFF00000);
3921 /* now adjust by 369 years to make the secs since 1970 */
3922 d -= TIME_FIXUP_CONSTANT;
3927 ret = (time_t)(d+0.5);
3929 /* this takes us from kludge-GMT to real GMT */
3930 ret += TimeDiff(ret) - serverzone;
3936 /****************************************************************************
3937 put a 8 byte filetime from a time_t
3938 This takes real GMT as input and converts to kludge-GMT
3939 ****************************************************************************/
3940 void put_long_date(char *p,time_t t)
3946 SIVAL(p,0,0); SIVAL(p,4,0);
3950 /* this converts GMT to kludge-GMT */
3951 t -= TimeDiff(t) - serverzone;
3955 d += TIME_FIXUP_CONSTANT;
3959 thigh = (uint32)(d * (1.0/(4.0*(double)(1<<30))));
3960 tlow = (uint32)(d - ((double)thigh)*4.0*(double)(1<<30));
3966 /*******************************************************************
3967 sub strings with useful parameters
3968 ********************************************************************/
3969 void standard_sub_basic(char *s)
3971 if (!strchr(s,'%')) return;
3973 string_sub(s,"%R",remote_proto);
3974 string_sub(s,"%a",remote_arch);
3975 string_sub(s,"%m",remote_machine);
3976 string_sub(s,"%L",local_machine);
3978 if (!strchr(s,'%')) return;
3980 string_sub(s,"%v",VERSION);
3981 string_sub(s,"%h",myhostname);
3982 string_sub(s,"%U",sesssetup_user);
3984 if (!strchr(s,'%')) return;
3986 string_sub(s,"%I",Client_info.addr);
3987 string_sub(s,"%M",Client_info.name);
3988 string_sub(s,"%T",timestring());
3990 if (!strchr(s,'%')) return;
3994 sprintf(pidstr,"%d",(int)getpid());
3995 string_sub(s,"%d",pidstr);
3998 if (!strchr(s,'%')) return;
4001 struct passwd *pass = Get_Pwnam(sesssetup_user,False);
4003 string_sub(s,"%G",gidtoname(pass->pw_gid));
4009 /*******************************************************************
4010 write a string in unicoode format
4011 ********************************************************************/
4012 int PutUniCode(char *dst,char *src)
4016 dst[ret++] = src[0];
4026 pstring smbrun_path = SMBRUN;
4028 /****************************************************************************
4029 run a command via system() using smbrun
4030 ****************************************************************************/
4031 int smbrun(char *cmd,char *outfile)
4036 if (!file_exist(smbrun_path,NULL))
4038 DEBUG(0,("SMBRUN ERROR: Can't find %s. Installation problem?\n",smbrun_path));
4042 sprintf(syscmd,"%s \"(%s 2>&1) > %s\"",
4044 outfile?outfile:"/dev/null");
4046 DEBUG(5,("smbrun - running %s ",syscmd));
4047 ret = system(syscmd);
4048 DEBUG(5,("gave %d\n",ret));
4053 /****************************************************************************
4054 a wrapper for gethostbyname() that tries with all lower and all upper case
4055 if the initial name fails
4056 ****************************************************************************/
4057 struct hostent *Get_Hostbyname(char *name)
4059 char *name2 = strdup(name);
4060 struct hostent *ret;
4064 DEBUG(0,("Memory allocation error in Get_Hostbyname! panic\n"));
4068 if (!isalnum(*name2))
4074 ret = gethostbyname(name2);
4081 /* try with all lowercase */
4083 ret = gethostbyname(name2);
4090 /* try with all uppercase */
4092 ret = gethostbyname(name2);
4099 /* nothing works :-( */
4105 /****************************************************************************
4106 check if a process exists. Does this work on all unixes?
4107 ****************************************************************************/
4108 BOOL process_exists(int pid)
4112 sprintf(s,"/proc/%d",pid);
4113 return(directory_exist(s,NULL));
4116 static BOOL tested=False;
4117 static BOOL ok=False;
4121 sprintf(s,"/proc/%05d",getpid());
4122 ok = file_exist(s,NULL);
4125 sprintf(s,"/proc/%05d",pid);
4126 return(file_exist(s,NULL));
4130 /* a best guess for non root access */
4131 if (geteuid() != 0) return(True);
4133 /* otherwise use kill */
4134 return(pid == getpid() || kill(pid,0) == 0);
4139 /*******************************************************************
4140 turn a uid into a user name
4141 ********************************************************************/
4142 char *uidtoname(int uid)
4144 static char name[40];
4145 struct passwd *pass = getpwuid(uid);
4146 if (pass) return(pass->pw_name);
4147 sprintf(name,"%d",uid);
4151 /*******************************************************************
4152 turn a gid into a group name
4153 ********************************************************************/
4154 char *gidtoname(int gid)
4156 static char name[40];
4157 struct group *grp = getgrgid(gid);
4158 if (grp) return(grp->gr_name);
4159 sprintf(name,"%d",gid);
4163 /*******************************************************************
4165 ********************************************************************/
4166 void BlockSignals(BOOL block)
4169 int block_mask = (sigmask(SIGTERM)|sigmask(SIGQUIT)|sigmask(SIGSEGV)
4170 |sigmask(SIGCHLD)|sigmask(SIGQUIT)|sigmask(SIGBUS)|
4173 sigblock(block_mask);
4175 sigunblock(block_mask);
4180 /*******************************************************************
4181 my own panic function - not suitable for general use
4182 ********************************************************************/
4183 void ajt_panic(void)
4185 pstring cmd = "/usr/bin/X11/xedit -display :0 /tmp/ERROR_FAULT &";
4191 #define DIRECT direct
4193 #define DIRECT dirent
4196 /*******************************************************************
4197 a readdir wrapper which just returns the file name
4198 also return the inode number if requested
4199 ********************************************************************/
4200 char *readdirname(void *p)
4205 if (!p) return(NULL);
4207 ptr = (struct DIRECT *)readdir(p);
4208 if (!ptr) return(NULL);
4210 dname = ptr->d_name;
4216 unix_to_dos(buf, True);
4222 if (telldir(p) < 0) return(NULL);
4226 /* this handles a broken compiler setup, causing a mixture
4227 of BSD and SYSV headers and libraries */
4229 static BOOL broken_readdir = False;
4230 if (!broken_readdir && !(*(dname)) && strequal("..",dname-2))
4232 DEBUG(0,("Your readdir() is broken. You have somehow mixed SYSV and BSD headers and libraries\n"));
4233 broken_readdir = True;
4245 #if (defined(SecureWare) && defined(SCO))
4246 /* This is needed due to needing the nap() function but we don't want
4247 to include the Xenix libraries since that will break other things...
4248 BTW: system call # 0x0c28 is the same as calling nap() */
4249 long nap(long milliseconds) {
4250 return syscall(0x0c28, milliseconds);
4254 #ifdef NO_INITGROUPS
4255 #include <sys/types.h>
4260 #define NULL (void *)0
4263 /****************************************************************************
4264 some systems don't have an initgroups call
4265 ****************************************************************************/
4266 int initgroups(char *name,gid_t id)
4269 /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
4272 gid_t grouplst[NGROUPS_MAX];
4279 while (i < NGROUPS_MAX &&
4280 ((g = (struct group *)getgrent()) != (struct group *)NULL))
4282 if (g->gr_gid == id)
4286 while (gr && (*gr != (char)NULL)) {
4287 if (strcmp(name,gr) == 0) {
4288 grouplst[i] = g->gr_gid;
4293 gr = g->gr_mem[++j];
4297 return(setgroups(i,grouplst));
4305 /* undo the wrapping temporarily */
4310 /****************************************************************************
4311 wrapper for malloc() to catch memory errors
4312 ****************************************************************************/
4313 void *malloc_wrapped(int size,char *file,int line)
4315 #ifdef xx_old_malloc
4316 void *res = xx_old_malloc(size);
4318 void *res = malloc(size);
4320 DEBUG(3,("Malloc called from %s(%d) with size=%d gave ptr=0x%X\n",
4322 size,(unsigned int)res));
4326 /****************************************************************************
4327 wrapper for realloc() to catch memory errors
4328 ****************************************************************************/
4329 void *realloc_wrapped(void *ptr,int size,char *file,int line)
4331 #ifdef xx_old_realloc
4332 void *res = xx_old_realloc(ptr,size);
4334 void *res = realloc(ptr,size);
4336 DEBUG(3,("Realloc\n"));
4337 DEBUG(3,("free called from %s(%d) with ptr=0x%X\n",
4339 (unsigned int)ptr));
4340 DEBUG(3,("Malloc called from %s(%d) with size=%d gave ptr=0x%X\n",
4342 size,(unsigned int)res));
4346 /****************************************************************************
4347 wrapper for free() to catch memory errors
4348 ****************************************************************************/
4349 void free_wrapped(void *ptr,char *file,int line)
4356 DEBUG(3,("free called from %s(%d) with ptr=0x%X\n",
4357 file,line,(unsigned int)ptr));
4361 /* and re-do the define for spots lower in this file */
4362 #define malloc(size) malloc_wrapped(size,__FILE__,__LINE__)
4363 #define realloc(ptr,size) realloc_wrapped(ptr,size,__FILE__,__LINE__)
4364 #define free(ptr) free_wrapped(ptr,__FILE__,__LINE__)
4368 #ifdef REPLACE_STRSTR
4369 /****************************************************************************
4370 Mips version of strstr doesn't seem to work correctly.
4371 There is a #define in includes.h to redirect calls to this function.
4372 ****************************************************************************/
4373 char *Strstr(char *s, char *p)
4375 int len = strlen(p);
4377 while ( *s != '\0' ) {
4378 if ( strncmp(s, p, len) == 0 )
4385 #endif /* REPLACE_STRSTR */
4388 #ifdef REPLACE_MKTIME
4389 /*******************************************************************
4390 a mktime() replacement for those who don't have it - contributed by
4391 C.A. Lademann <cal@zls.com>
4392 ********************************************************************/
4394 #define HOUR 60*MINUTE
4396 #define YEAR 365*DAY
4397 time_t Mktime(struct tm *t)
4401 int mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
4407 epoch = (t->tm_year - 70) * YEAR +
4408 (t->tm_year / 4 - 70 / 4 - t->tm_year / 100) * DAY;
4413 for(i = 0; i < t->tm_mon; i++) {
4414 epoch += mon [m] * DAY;
4415 if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
4424 epoch += (t->tm_mday - 1) * DAY;
4425 epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec;
4427 if((u = localtime(&epoch)) != NULL) {
4428 t->tm_sec = u->tm_sec;
4429 t->tm_min = u->tm_min;
4430 t->tm_hour = u->tm_hour;
4431 t->tm_mday = u->tm_mday;
4432 t->tm_mon = u->tm_mon;
4433 t->tm_year = u->tm_year;
4434 t->tm_wday = u->tm_wday;
4435 t->tm_yday = u->tm_yday;
4436 t->tm_isdst = u->tm_isdst;
4438 memcpy(t->tm_name, u->tm_name, LTZNMAX);
4444 #endif /* REPLACE_MKTIME */
4448 #ifdef REPLACE_RENAME
4449 /* Rename a file. (from libiberty in GNU binutils) */
4455 if (link (zfrom, zto) < 0)
4457 if (errno != EEXIST)
4459 if (unlink (zto) < 0
4460 || link (zfrom, zto) < 0)
4463 return unlink (zfrom);
4468 #ifdef REPLACE_INNETGR
4470 * Search for a match in a netgroup. This replaces it on broken systems.
4472 int InNetGr(group, host, user, dom)
4473 char *group, *host, *user, *dom;
4475 char *hst, *usr, *dm;
4478 while (getnetgrent(&hst, &usr, &dm))
4479 if (((host == 0) || (hst == 0) || !strcmp(host, hst)) &&
4480 ((user == 0) || (usr == 0) || !strcmp(user, usr)) &&
4481 ((dom == 0) || (dm == 0) || !strcmp(dom, dm))) {
4493 /*******************************************************************
4494 a wrapper around memcpy for diagnostic purposes
4495 ********************************************************************/
4496 void *memcpy_wrapped(void *d,void *s,int l,char *fname,int line)
4498 if (l>64 && (((int)d)%4) != (((int)s)%4))
4499 DEBUG(4,("Misaligned memcpy(0x%X,0x%X,%d) at %s(%d)\n",d,s,l,fname,line));
4500 #ifdef xx_old_memcpy
4501 return(xx_old_memcpy(d,s,l));
4503 return(memcpy(d,s,l));
4506 #define memcpy(d,s,l) memcpy_wrapped(d,s,l,__FILE__,__LINE__)