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