1 /*
2 
3     File: common.c
4 
5     Copyright (C) 1998-2006 Christophe GRENIER <grenier@cgsecurity.org>
6 
7     This software 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.
11 
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.
16 
17     You should have received a copy of the GNU General Public License along
18     with this program; if not, write the Free Software Foundation, Inc., 51
19     Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 
21  */
22 
23 
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27 
28 #include <stdio.h>
29 #include <ctype.h>
30 #ifdef HAVE_STDLIB_H
31 #include <stdlib.h>
32 #endif
33 #ifdef HAVE_MALLOC_H
34 #include <malloc.h>
35 #endif
36 #ifdef HAVE_STRING_H
37 #include <string.h>
38 #endif
39 #ifdef __MINGW32__
40 #ifdef HAVE_IO_H
41 #include <io.h>
42 #endif
43 #endif
44 #ifdef HAVE_TIME_H
45 #include <time.h>
46 #endif
47 #include <assert.h>
48 #include "types.h"
49 #include "common.h"
50 #include "log.h"
51 
52 static int32_t secwest=0;
53 
54 static unsigned int up2power_aux(const unsigned int number);
55 
56 /* coverity[+alloc] */
MALLOC(size_t size)57 void *MALLOC(size_t size)
58 {
59   void *res;
60   assert(size>0);
61   /* Warning, memory leak checker must be posix_memalign/memalign aware, otherwise  *
62    * reports may look strange. Aligned memory is required if the buffer is *
63    * used for read/write operation with a file opened with O_DIRECT        */
64 #if defined(HAVE_POSIX_MEMALIGN)
65   if(size>=512)
66   {
67     if(posix_memalign(&res,4096,size)==0)
68     {
69       memset(res,0,size);
70       return res;
71     }
72   }
73 #elif defined(HAVE_MEMALIGN)
74   if(size>=512)
75   {
76     if((res=memalign(4096, size))!=NULL)
77     {
78       memset(res,0,size);
79       return res;
80     }
81   }
82 #endif
83   if((res=malloc(size))==NULL)
84   {
85     log_critical("\nCan't allocate %lu bytes of memory.\n", (long unsigned)size);
86     log_close();
87     exit(EXIT_FAILURE);
88   }
89   memset(res,0,size);
90   return res;
91 }
92 
93 #ifndef HAVE_SNPRINTF
snprintf(char * str,size_t size,const char * format,...)94 int snprintf(char *str, size_t size, const char *format, ...)
95 {
96   int res;
97   va_list ap;
98   va_start(ap,format);
99   res=vsnprintf(str, size, format, ap);
100   va_end(ap);
101   return res;
102 }
103 #endif
104 
105 #ifndef HAVE_VSNPRINTF
vsnprintf(char * str,size_t size,const char * format,va_list ap)106 int vsnprintf(char *str, size_t size, const char *format, va_list ap)
107 {
108   return vsprintf(str,format,ap);
109 }
110 #endif
111 
112 #ifndef HAVE_STRNCASECMP
113 /** Case-insensitive, size-constrained, lexical comparison.
114  *
115  * Compares a specified maximum number of characters of two strings for
116  * lexical equivalence in a case-insensitive manner.
117  *
118  * @param[in] s1 - The first string to be compared.
119  * @param[in] s2 - The second string to be compared.
120  * @param[in] len - The maximum number of characters to compare.
121  *
122  * @return Zero if at least @p len characters of @p s1 are the same as
123  *    the corresponding characters in @p s2 within the ASCII printable
124  *    range; a value less than zero if @p s1 is lexically less than
125  *    @p s2; or a value greater than zero if @p s1 is lexically greater
126  *    than @p s2.
127  *
128  * @internal
129  */
strncasecmp(const char * s1,const char * s2,size_t len)130 int strncasecmp(const char * s1, const char * s2, size_t len)
131 {
132   while (*s1 && (*s1 == *s2 || tolower(*s1) == tolower(*s2)))
133   {
134     len--;
135     if (len == 0)
136       return 0;
137     s1++;
138     s2++;
139   }
140   return (int)*(const unsigned char *)s1 - (int)*(const unsigned char *)s2;
141 }
142 #endif
143 
144 #ifndef HAVE_STRCASESTR
strcasestr(const char * haystack,const char * needle)145 char * strcasestr (const char *haystack, const char *needle)
146 {
147   const char *p, *startn = NULL, *np = NULL;
148   for (p = haystack; *p; p++)
149   {
150     if (np)
151     {
152       if (toupper(*p) == toupper(*np))
153       {
154 	if (!*++np)
155 	  return startn;
156       }
157       else
158 	np = NULL;
159     }
160     else if (toupper(*p) == toupper(*needle))
161     {
162       np = needle + 1;
163       startn = p;
164     }
165   }
166   return NULL;
167 }
168 #endif
169 
170 #if ! defined(HAVE_LOCALTIME_R) && ! defined(__MINGW32__)
localtime_r(const time_t * timep,struct tm * result)171 struct tm *localtime_r(const time_t *timep, struct tm *result)
172 {
173   return localtime(timep);
174 }
175 #endif
176 
up2power(const unsigned int number)177 unsigned int up2power(const unsigned int number)
178 {
179   /* log_trace("up2power(%u)=>%u\n",number, (1<<up2power_aux(number-1))); */
180   if(number==0)
181     return 1;
182   return (1<<up2power_aux(number-1));
183 }
184 
up2power_aux(const unsigned int number)185 static unsigned int up2power_aux(const unsigned int number)
186 {
187   if(number==0)
188 	return 0;
189   else
190 	return(1+up2power_aux(number/2));
191 }
192 
set_part_name(partition_t * partition,const char * src,const unsigned int max_size)193 void set_part_name(partition_t *partition, const char *src, const unsigned int max_size)
194 {
195   unsigned int i;
196   for(i=0; i<sizeof(partition->fsname)-1 && i<max_size && src[i]!='\0'; i++)
197     partition->fsname[i]=src[i];
198   partition->fsname[i]='\0';
199 }
200 
set_part_name_chomp(partition_t * partition,const unsigned char * src,const unsigned int max_size)201 void set_part_name_chomp(partition_t *partition, const unsigned char *src, const unsigned int max_size)
202 {
203   unsigned int i;
204   for(i=0; i<sizeof(partition->fsname)-1 && i<max_size && src[i]!='\0'; i++)
205     partition->fsname[i]=src[i];
206   while(i>0 && src[i-1]==' ')
207     i--;
208   partition->fsname[i]='\0';
209 }
210 
strip_dup(char * str)211 char* strip_dup(char* str)
212 {
213   unsigned int i;
214   char *end;
215   while(isspace(*str))
216     str++;
217   end=str;
218   for (i = 0; str[i] != 0; i++)
219     if (!isspace (str[i]))
220       end=&str[i];
221   if(str == end)
222     return NULL;
223   *(end+1) = 0;
224   return strdup (str);
225 }
226 
227 /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */
228 
date_dos2unix(const unsigned short f_time,const unsigned short f_date)229 int date_dos2unix(const unsigned short f_time, const unsigned short f_date)
230 {
231   static const int day_n[] = { 0,31,59,90,120,151,181,212,243,273,304,334,0,0,0,0 };
232   /* JanFebMarApr May Jun Jul Aug Sep Oct Nov Dec */
233 
234   int month,year,secs;
235 
236   /* first subtract and mask after that... Otherwise, if
237      f_date == 0, bad things happen */
238   month = ((f_date >> 5) - 1) & 15;
239   year = f_date >> 9;
240   secs = (f_time & 31)*2+60*((f_time >> 5) & 63)+(f_time >> 11)*3600+86400*
241     ((f_date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 &&
242       month < 2 ? 1 : 0)+3653);
243   /* days since 1.1.70 plus 80's leap day */
244   return secs+secwest;
245 }
246 
set_secwest(void)247 void set_secwest(void)
248 {
249   const time_t t = time(NULL);
250 #if defined(__MINGW32__)
251   const struct  tm *tmptr = localtime(&t);
252 #else
253   struct  tm tmp;
254   const struct  tm *tmptr = localtime_r(&t,&tmp);
255 #endif
256 #ifdef HAVE_STRUCT_TM_TM_GMTOFF
257   if(tmptr)
258     secwest = -1 * tmptr->tm_gmtoff;
259   else
260     secwest = 0;
261 #elif defined (DJGPP) || defined(__ANDROID__)
262   secwest = 0;
263 #else
264 #if defined (__CYGWIN__)
265   secwest = _timezone;
266 #else
267   secwest = timezone;
268 #endif
269   /* account for daylight savings */
270   if (tmptr && tmptr->tm_isdst)
271     secwest -= 3600;
272 #endif
273 }
274 
275 /**
276  * td_ntfs2utc - Convert an NTFS time to Unix time
277  * @time:  An NTFS time in 100ns units since 1601
278  *
279  * NTFS stores times as the number of 100ns intervals since January 1st 1601 at
280  * 00:00 UTC.  This system will not suffer from Y2K problems until ~57000AD.
281  *
282  * Return:  n  A Unix time (number of seconds since 1970)
283  */
284 #define NTFS_TIME_OFFSET ((int64_t)(369 * 365 + 89) * 24 * 3600 * 10000000)
td_ntfs2utc(int64_t ntfstime)285 time_t td_ntfs2utc (int64_t ntfstime)
286 {
287   return (ntfstime - (NTFS_TIME_OFFSET)) / 10000000;
288 }
289 
check_command(char ** current_cmd,const char * cmd,size_t n)290 int check_command(char **current_cmd, const char *cmd, size_t n)
291 {
292   const int res=strncmp(*current_cmd, cmd, n);
293   if(res==0)
294     (*current_cmd)+=n;
295   return res;
296 }
297 
skip_comma_in_command(char ** current_cmd)298 void skip_comma_in_command(char **current_cmd)
299 {
300   while(*current_cmd[0]==',')
301     (*current_cmd)++;
302 }
303 
get_int_from_command(char ** current_cmd)304 uint64_t get_int_from_command(char **current_cmd)
305 {
306   uint64_t tmp=0;
307   while(*current_cmd[0] >='0' && *current_cmd[0] <= '9')
308   {
309     tmp = tmp * 10 + *current_cmd[0] - '0';
310     (*current_cmd)++;
311   }
312   return tmp;
313 }
314