1 /**
2 * Copyright (C) 2008 Happy Fish / YuQing
3 *
4 * FastDFS may be copied only under the terms of the GNU General
5 * Public License V3, which may be found in the FastDFS source kit.
6 * Please visit the FastDFS Home Page http://www.fastken.com/ for more detail.
7 **/
8 
9 #include <time.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <ctype.h>
14 #include <unistd.h>
15 #include <signal.h>
16 #include <inttypes.h>
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <netinet/in.h>
20 #include <fcntl.h>
21 #include <errno.h>
22 #include <sys/file.h>
23 #include <dirent.h>
24 #include <grp.h>
25 #include <pwd.h>
26 #include <math.h>
27 
28 #include "shared_func.h"
29 #include "logger.h"
30 #include "sockopt.h"
31 
32 #ifdef OS_LINUX
33 #include <sys/sysinfo.h>
34 #else
35 #ifdef OS_FREEBSD
36 #include <sys/sysctl.h>
37 #endif
38 #endif
39 
formatDatetime(const time_t nTime,const char * szDateFormat,char * buff,const int buff_size)40 char *formatDatetime(const time_t nTime, \
41 	const char *szDateFormat, \
42 	char *buff, const int buff_size)
43 {
44 	static char szDateBuff[128];
45 	struct tm tmTime;
46 	int size;
47 
48 	localtime_r(&nTime, &tmTime);
49 	if (buff == NULL)
50 	{
51 		buff = szDateBuff;
52 		size = sizeof(szDateBuff);
53 	}
54 	else
55 	{
56 		size = buff_size;
57 	}
58 
59 	*buff = '\0';
60 	strftime(buff, size, szDateFormat, &tmTime);
61 
62 	return buff;
63 }
64 
getCharLen(const char * s)65 int getCharLen(const char *s)
66 {
67 	unsigned char *p;
68 	int count = 0;
69 
70 	p = (unsigned char *)s;
71 	while (*p != '\0')
72 	{
73 		if (*p > 127)
74 		{
75 			if (*(++p) != '\0')
76 			{
77 				p++;
78 			}
79 		}
80 		else
81 		{
82 			p++;
83 		}
84 
85 		count++;
86 	}
87 
88 	return count;
89 }
90 
replaceCRLF2Space(char * s)91 char *replaceCRLF2Space(char *s)
92 {
93 	char *p = s;
94 
95 	while (*p != '\0')
96 	{
97 		if (*p == '\r' || *p == '\n')
98 		{
99 			*p = ' ';
100 		}
101 
102 		p++;
103 	}
104 
105 	return s;
106 }
107 
getAbsolutePath(const char * filename,char * szAbsPath,const int pathSize)108 char *getAbsolutePath(const char *filename, char *szAbsPath, \
109 		const int pathSize)
110 {
111 	char *p;
112 	int nPathLen;
113 	char szPath[1024];
114 	char cwd[256];
115 
116 	p = strrchr(filename, '/');
117 	if (p == NULL)
118 	{
119 		szPath[0] = '\0';
120 	}
121 	else
122 	{
123 		nPathLen = p - filename;
124 		if (nPathLen >= sizeof(szPath))
125 		{
126 			logError("file: "__FILE__", line: %d, " \
127 				"filename length: %d is too long, exceeds %d",\
128 				__LINE__, nPathLen, (int)sizeof(szPath));
129 			return NULL;
130 		}
131 
132 		memcpy(szPath, filename, nPathLen);
133 		szPath[nPathLen] = '\0';
134 	}
135 
136 	if (szPath[0] == '/')
137 	{
138 		snprintf(szAbsPath, pathSize, "%s", szPath);
139 	}
140 	else
141 	{
142 		if (getcwd(cwd, sizeof(cwd)) == NULL)
143 		{
144 			logError("file: "__FILE__", line: %d, " \
145 				"call getcwd fail, errno: %d, error info: %s", \
146 				__LINE__, errno, STRERROR(errno));
147 			return NULL;
148 		}
149 
150 		nPathLen = strlen(cwd);
151 		if (cwd[nPathLen - 1] == '/')
152 		{
153 			cwd[nPathLen - 1] = '\0';
154 		}
155 
156 		if (szPath[0] != '\0')
157 		{
158 			snprintf(szAbsPath, pathSize, "%s/%s", cwd, szPath);
159 		}
160 		else
161 		{
162 			snprintf(szAbsPath, pathSize, "%s", cwd);
163 		}
164 	}
165 
166 	return szAbsPath;
167 }
168 
getExeAbsoluteFilename(const char * exeFilename,char * szAbsFilename,const int maxSize)169 char *getExeAbsoluteFilename(const char *exeFilename, char *szAbsFilename, \
170 		const int maxSize)
171 {
172 	const char *filename;
173 	const char *p;
174 	int nFileLen;
175 	int nPathLen;
176 	char cwd[256];
177 	char szPath[1024];
178 
179 	nFileLen = strlen(exeFilename);
180 	if (nFileLen >= sizeof(szPath))
181 	{
182 		logError("file: "__FILE__", line: %d, " \
183 			"filename length: %d is too long, exceeds %d!", \
184 			__LINE__, nFileLen, (int)sizeof(szPath));
185 		return NULL;
186 	}
187 
188 	p = strrchr(exeFilename, '/');
189 	if (p == NULL)
190 	{
191 		int i;
192 		char *search_paths[] = {"/bin", "/usr/bin", "/usr/local/bin"};
193 
194 		*szPath = '\0';
195 		filename = exeFilename;
196 		for (i=0; i<3; i++)
197 		{
198 			snprintf(cwd, sizeof(cwd), "%s/%s", \
199 				search_paths[i], filename);
200 			if (fileExists(cwd))
201 			{
202 				strcpy(szPath, search_paths[i]);
203 				break;
204 			}
205 		}
206 
207 		if (*szPath == '\0')
208 		{
209 			if (!fileExists(filename))
210 			{
211 				logError("file: "__FILE__", line: %d, " \
212 					"can't find exe file %s!", __LINE__, \
213 					filename);
214 				return NULL;
215 			}
216 		}
217 		else
218 		{
219 			snprintf(szAbsFilename, maxSize, "%s/%s", \
220 				szPath, filename);
221 			return szAbsFilename;
222 		}
223 	}
224 	else
225 	{
226 		filename = p + 1;
227 		nPathLen = p - exeFilename;
228 		memcpy(szPath, exeFilename, nPathLen);
229 		szPath[nPathLen] = '\0';
230 	}
231 
232 	if (*szPath == '/')
233 	{
234 		snprintf(szAbsFilename, maxSize, "%s/%s", szPath, filename);
235 	}
236 	else
237 	{
238 		if (getcwd(cwd, sizeof(cwd)) == NULL)
239 		{
240 			logError("file: "__FILE__", line: %d, " \
241 				"call getcwd fail, errno: %d, error info: %s", \
242 				__LINE__, errno, STRERROR(errno));
243 			return NULL;
244 		}
245 
246 		nPathLen = strlen(cwd);
247 		if (cwd[nPathLen - 1] == '/')
248 		{
249 			cwd[nPathLen - 1] = '\0';
250 		}
251 
252 		if (*szPath != '\0')
253 		{
254 			snprintf(szAbsFilename, maxSize, "%s/%s/%s", \
255 				cwd, szPath, filename);
256 		}
257 		else
258 		{
259 			snprintf(szAbsFilename, maxSize, "%s/%s", \
260 				cwd, filename);
261 		}
262 	}
263 
264 	return szAbsFilename;
265 }
266 
267 #ifndef WIN32
getProccessCount(const char * progName,const bool bAllOwners)268 int getProccessCount(const char *progName, const bool bAllOwners)
269 {
270 	int *pids = NULL;
271 	return getUserProcIds(progName, bAllOwners, pids, 0);
272 }
273 
getUserProcIds(const char * progName,const bool bAllOwners,int pids[],const int arrSize)274 int getUserProcIds(const char *progName, const bool bAllOwners, \
275 		int pids[], const int arrSize)
276 {
277 	char path[128]="/proc";
278 	char fullpath[128];
279 	struct stat statbuf;
280 	struct dirent *dirp;
281 	DIR  *dp;
282 	int  myuid=getuid();
283 	int  fd;
284 	char filepath[128];
285 	char buf[256];
286 	char *ptr;
287 	int  nbytes;
288 	char procname[64];
289 	int  cnt=0;
290 	char *pTargetProg;
291 
292 	if ((dp = opendir(path)) == NULL)
293 	{
294 		return -1;
295 	}
296 
297 	pTargetProg = (char *)malloc(strlen(progName) + 1);
298 	if (pTargetProg == NULL)
299 	{
300 		logError("file: "__FILE__", line: %d, " \
301 			"malloc %d bytes fail", __LINE__, \
302 			(int)strlen(progName) + 1);
303 		return -1;
304 	}
305 
306 	ptr = strrchr(progName, '/');
307 	if (ptr == NULL)
308 	{
309 		strcpy(pTargetProg, progName);
310 	}
311 	else
312 	{
313 		strcpy(pTargetProg, ptr + 1);
314 	}
315 
316 	while( (dirp = readdir(dp)) != NULL )
317 	{
318 		if (strcmp(dirp->d_name, ".")==0 || strcmp(dirp->d_name, "..")==0 )
319 		{
320 			continue;
321 		}
322 
323 		sprintf(fullpath, "%s/%s", path, dirp->d_name);
324 		memset(&statbuf, 0, sizeof(statbuf));
325 		if (lstat(fullpath, &statbuf)<0)
326 		{
327 			continue;
328 		}
329 
330 		if ((bAllOwners || (statbuf.st_uid == myuid)) && S_ISDIR(statbuf.st_mode))
331 		{
332 			sprintf(filepath, "%s/cmdline", fullpath);
333 			if ((fd = open(filepath, O_RDONLY))<0)
334 			{
335 				continue;
336 			}
337 
338 			memset(buf, 0, 256);
339 			if ((nbytes = read(fd, buf, 255)) < 0){
340 				close(fd);
341 				continue;
342 			}
343 			close(fd);
344 
345 			if (*buf == '\0')
346 			{
347 				continue;
348 			}
349 
350 			ptr = strrchr(buf, '/');
351 			if (ptr == NULL)
352 			{
353 				snprintf(procname, 64, "%s", buf);
354 			}
355 			else
356 			{
357 				snprintf(procname, 64, "%s", ptr + 1);
358 			}
359 
360 			if (strcmp(procname, pTargetProg) == 0)
361 			{
362 				if (pids != NULL)
363 				{
364 					if (cnt >= arrSize)
365 					{
366 						break;
367 					}
368 					pids[cnt] = atoi(dirp->d_name);
369 				}
370 
371 				cnt++;
372 			}
373 		}
374 	}
375 	free(pTargetProg);
376 
377 	closedir(dp);
378 	return cnt;
379 }
380 
getExecResult(const char * command,char * output,const int buff_size)381 int getExecResult(const char *command, char *output, const int buff_size)
382 {
383 	FILE *fp;
384 	char *pCurrent;
385 	int bytes_read;
386 	int remain_bytes;
387 
388 	if((fp=popen(command, "r")) == NULL)
389 	{
390         *output = '\0';
391 		return errno != 0 ? errno : EMFILE;
392 	}
393 
394 	pCurrent = output;
395 	remain_bytes = buff_size - 1;
396 	while (remain_bytes > 0 && \
397 		(bytes_read=fread(pCurrent, 1, remain_bytes, fp)) > 0)
398 	{
399 		pCurrent += bytes_read;
400 		remain_bytes -= bytes_read;
401 	}
402 	pclose(fp);
403 
404 	*pCurrent = '\0';
405 	return remain_bytes > 0 ? 0 : ENOSPC;
406 }
407 
408 #endif
409 
toLowercase(char * src)410 char *toLowercase(char *src)
411 {
412 	char *p;
413 
414 	p = src;
415 	while (*p != '\0')
416 	{
417 		if (*p >= 'A' && *p <= 'Z')
418 		{
419 			*p += 32;
420 		}
421 		p++;
422 	}
423 
424 	return src;
425 }
426 
toUppercase(char * src)427 char *toUppercase(char *src)
428 {
429 	char *p;
430 
431 	p = src;
432 	while (*p != '\0')
433 	{
434 		if (*p >= 'a' && *p <= 'z')
435 		{
436 			*p -= 32;
437 		}
438 		p++;
439 	}
440 
441 	return src;
442 }
443 
daemon_init(bool bCloseFiles)444 void daemon_init(bool bCloseFiles)
445 {
446 #ifndef WIN32
447 	pid_t pid;
448 	int i;
449 
450 	if((pid=fork()) != 0)
451 	{
452 		exit(0);
453 	}
454 
455 	setsid();
456 
457 	if((pid=fork()) != 0)
458 	{
459 		exit(0);
460 	}
461 
462 #ifdef DEBUG_FLAG
463 	#define MAX_CORE_FILE_SIZE  (256 * 1024 * 1024)
464 	if (set_rlimit(RLIMIT_CORE, MAX_CORE_FILE_SIZE) != 0)
465 	{
466 		logWarning("file: "__FILE__", line: %d, " \
467 			"set max core dump file size to %d MB fail, " \
468 			"errno: %d, error info: %s", \
469 			__LINE__, MAX_CORE_FILE_SIZE / (1024 * 1024), \
470 			errno, STRERROR(errno));
471 	}
472 #else
473 	if (chdir("/") != 0)
474 	{
475 		logWarning("file: "__FILE__", line: %d, " \
476 			"change directory to / fail, " \
477 			"errno: %d, error info: %s", \
478 			__LINE__, errno, STRERROR(errno));
479 	}
480 #endif
481 
482 	if (bCloseFiles)
483 	{
484 		for(i=0; i<=2; i++)
485 		{
486 			close(i);
487 		}
488 	}
489 #endif
490 
491 	return;
492 }
493 
bin2hex(const char * s,const int len,char * szHexBuff)494 char *bin2hex(const char *s, const int len, char *szHexBuff)
495 {
496 	unsigned char *p;
497 	unsigned char *pEnd;
498 	int nLen;
499 
500 	nLen = 0;
501 	pEnd = (unsigned char *)s + len;
502 	for (p=(unsigned char *)s; p<pEnd; p++)
503 	{
504 		nLen += sprintf(szHexBuff + nLen, "%02x", *p);
505 	}
506 
507 	szHexBuff[nLen] = '\0';
508 	return szHexBuff;
509 }
510 
hex2bin(const char * s,char * szBinBuff,int * nDestLen)511 char *hex2bin(const char *s, char *szBinBuff, int *nDestLen)
512 {
513         char buff[3];
514 	char *pSrc;
515 	int nSrcLen;
516 	char *pDest;
517 	char *pDestEnd;
518 
519 	nSrcLen = strlen(s);
520         if (nSrcLen == 0)
521         {
522           *nDestLen = 0;
523           szBinBuff[0] = '\0';
524           return szBinBuff;
525         }
526 
527 	*nDestLen = nSrcLen / 2;
528 	pSrc = (char *)s;
529         buff[2] = '\0';
530 
531 	pDestEnd = szBinBuff + (*nDestLen);
532 	for (pDest=szBinBuff; pDest<pDestEnd; pDest++)
533 	{
534 		buff[0] = *pSrc++;
535 		buff[1] = *pSrc++;
536 		*pDest = (char)strtol(buff, NULL, 16);
537 	}
538 
539 	*pDest = '\0';
540 	return szBinBuff;
541 }
542 
printBuffHex(const char * s,const int len)543 void printBuffHex(const char *s, const int len)
544 {
545 	unsigned char *p;
546 	int i;
547 
548 	p = (unsigned char *)s;
549 	for (i=0; i<len; i++)
550 	{
551 		printf("%02X", *p);
552 		p++;
553 	}
554 	printf("\n");
555 }
556 
trim_left(char * pStr)557 char *trim_left(char *pStr)
558 {
559 	char *p;
560 	char *pEnd;
561 	int nDestLen;
562 
563 	pEnd = pStr + strlen(pStr);
564 	for (p=pStr; p<pEnd; p++)
565 	{
566 		if (!(' ' == *p|| '\n' == *p || '\r' == *p || '\t' == *p))
567 		{
568 			break;
569 		}
570 	}
571 
572 	if ( p == pStr)
573 	{
574 		return pStr;
575 	}
576 
577 	nDestLen = (pEnd - p) + 1; //including \0
578 	memmove(pStr, p, nDestLen);
579 
580 	return pStr;
581 }
582 
trim_right(char * pStr)583 char *trim_right(char *pStr)
584 {
585 	int len;
586 	char *p;
587 	char *pEnd;
588 
589 	len = strlen(pStr);
590 	if (len == 0)
591 	{
592 		return pStr;
593 	}
594 
595 	pEnd = pStr + len - 1;
596 	for (p = pEnd;  p>=pStr; p--)
597 	{
598 		if (!(' ' == *p || '\n' == *p || '\r' == *p || '\t' == *p))
599 		{
600 			break;
601 		}
602 	}
603 
604 	if (p != pEnd)
605 	{
606 		*(p+1) = '\0';
607 	}
608 
609 	return pStr;
610 }
611 
trim(char * pStr)612 char *trim(char *pStr)
613 {
614 	trim_right(pStr);
615 	trim_left(pStr);
616 	return pStr;
617 }
618 
string_ltrim(string_t * s)619 void string_ltrim(string_t *s)
620 {
621 	char *p;
622 	char *end;
623 
624 	end = s->str + s->len;
625 	for (p=s->str; p<end; p++)
626 	{
627 		if (!(' ' == *p|| '\n' == *p || '\r' == *p || '\t' == *p))
628 		{
629 			break;
630 		}
631 	}
632 
633 	if (p != s->str)
634     {
635         s->str = p;
636         s->len = end - p;
637     }
638 }
639 
string_rtrim(string_t * s)640 void string_rtrim(string_t *s)
641 {
642 	char *p;
643 	char *end;
644 
645 	if (s->len == 0)
646 	{
647 		return;
648 	}
649 
650 	end = s->str + s->len - 1;
651 	for (p = end; p >= s->str; p--)
652 	{
653 		if (!(' ' == *p || '\n' == *p || '\r' == *p || '\t' == *p))
654 		{
655 			break;
656 		}
657 	}
658 
659 	if (p != end)
660 	{
661         s->len = (p + 1) - s->str;
662 	}
663 }
664 
formatDateYYYYMMDDHHMISS(const time_t t,char * szDateBuff,const int nSize)665 char *formatDateYYYYMMDDHHMISS(const time_t t, char *szDateBuff, const int nSize)
666 {
667 	time_t timer = t;
668 	struct tm tm;
669 
670 	localtime_r(&timer, &tm);
671 
672 	snprintf(szDateBuff, nSize, "%04d%02d%02d%02d%02d%02d", \
673 		tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, \
674 		tm.tm_hour, tm.tm_min, tm.tm_sec);
675 
676 	return szDateBuff;
677 }
678 
getOccurCount(const char * src,const char seperator)679 int getOccurCount(const char *src, const char seperator)
680 {
681 	int count;
682 	char *p;
683 
684 	count = 0;
685 	p = strchr(src, seperator);
686 	while (p != NULL)
687 	{
688 		count++;
689 		p = strchr(p + 1, seperator);
690 	}
691 
692 	return count;
693 }
694 
split(char * src,const char seperator,const int nMaxCols,int * nColCount)695 char **split(char *src, const char seperator, const int nMaxCols, int *nColCount)
696 {
697 	char **pCols;
698 	char **pCurrent;
699 	char *p;
700 	int i;
701 	int nLastIndex;
702 
703 	if (src == NULL)
704 	{
705 		*nColCount = 0;
706 		return NULL;
707 	}
708 
709 	*nColCount = 1;
710 	p = strchr(src, seperator);
711 
712 	while (p != NULL)
713 	{
714 		(*nColCount)++;
715 		p = strchr(p + 1, seperator);
716 	}
717 
718 	if (nMaxCols > 0 && (*nColCount) > nMaxCols)
719 	{
720 		*nColCount = nMaxCols;
721 	}
722 
723 	pCurrent = pCols = (char **)malloc(sizeof(char *) * (*nColCount));
724 	if (pCols == NULL)
725 	{
726 		logError("file: "__FILE__", line: %d, " \
727 			"malloc %d bytes fail", __LINE__, \
728 			(int)sizeof(char *) * (*nColCount));
729 		return NULL;
730 	}
731 
732 	p = src;
733 	nLastIndex = *nColCount - 1;
734 	for (i=0; i<*nColCount; i++)
735 	{
736 		*pCurrent = p;
737 		pCurrent++;
738 
739 		p = strchr(p, seperator);
740 		if (i != nLastIndex)
741 		{
742 			*p = '\0';
743 			p++;
744 		}
745 	}
746 
747 	return pCols;
748 }
749 
freeSplit(char ** p)750 void freeSplit(char **p)
751 {
752 	if (p != NULL)
753 	{
754 		free(p);
755 	}
756 }
757 
splitEx(char * src,const char seperator,char ** pCols,const int nMaxCols)758 int splitEx(char *src, const char seperator, char **pCols, const int nMaxCols)
759 {
760 	char *p;
761 	char **pCurrent;
762 	int count = 0;
763 
764 	if (nMaxCols <= 0)
765 	{
766 		return 0;
767 	}
768 
769 	p = src;
770 	pCurrent = pCols;
771 
772 	while (true)
773 	{
774 		*pCurrent = p;
775 		pCurrent++;
776 
777 		count++;
778 		if (count >= nMaxCols)
779 		{
780 			break;
781 		}
782 
783 		p = strchr(p, seperator);
784 		if (p == NULL)
785 		{
786 			break;
787 		}
788 
789 		*p = '\0';
790 		p++;
791 	}
792 
793 	return count;
794 }
795 
fc_match_delim(const char * str,const char * delim)796 bool fc_match_delim(const char *str, const char *delim)
797 {
798     const char *sp;
799     const char *send;
800     const char *dp;
801     const char *dend;
802 
803     send = str + strlen(str);
804     dend = delim + strlen(delim);
805     for (sp=str; sp<send; sp++)
806     {
807         for (dp=delim; dp<dend; dp++)
808         {
809             if (*sp == *dp)
810             {
811                 break;
812             }
813         }
814 
815         if (dp == dend)
816         {
817             return false;
818         }
819     }
820 
821     return true;
822 }
823 
fc_split_string(char * src,const char * delim,char ** pCols,const int nMaxCols)824 int fc_split_string(char *src, const char *delim, char **pCols, const int nMaxCols)
825 {
826     char *token;
827     char *stringp;
828     int count = 0;
829 
830     stringp = src;
831     while ((token=strsep(&stringp, delim)) != NULL)
832     {
833         if (count >= nMaxCols)
834         {
835             break;
836         }
837 
838         if (fc_match_delim(token, delim))
839         {
840             continue;
841         }
842 
843         pCols[count++] = token;
844     }
845 
846     return count;
847 }
848 
my_strtok(char * src,const char * delim,char ** pCols,const int nMaxCols)849 int my_strtok(char *src, const char *delim, char **pCols, const int nMaxCols)
850 {
851     char *p;
852     char **pCurrent;
853     int count;
854     bool bWordEnd;
855 
856     if (src == NULL || pCols == NULL)
857     {
858         return -1;
859     }
860 
861     if (nMaxCols <= 0)
862     {
863         return 0;
864     }
865 
866     p = src;
867     pCurrent = pCols;
868 
869     while (*p != '\0')
870     {
871         if (strchr(delim, *p) == NULL)
872         {
873             break;
874         }
875         p++;
876     }
877 
878     if (*p == '\0')
879     {
880         return 0;
881     }
882 
883     *pCurrent = p;
884     bWordEnd = false;
885     count = 1;
886     if (count >= nMaxCols)
887     {
888         return count;
889     }
890 
891     while (*p != '\0')
892     {
893         if (strchr(delim, *p) != NULL)
894         {
895             *p = '\0';
896             bWordEnd = true;
897         }
898         else
899         {
900             if (bWordEnd)
901             {
902                 pCurrent++;
903                 *pCurrent = p;
904 
905                 count++;
906                 if (count >= nMaxCols)
907                 {
908                     break;
909                 }
910 
911                 bWordEnd = false;
912             }
913         }
914 
915         p++;
916     }
917 
918     return count;
919 }
920 
str_replace(const char * s,const int src_len,const char * replaced,const char * new_str,char * dest,const int dest_size)921 int str_replace(const char *s, const int src_len, const char *replaced,
922 		        const char *new_str, char *dest, const int dest_size)
923 {
924 	const char *pStart;
925 	const char *pEnd;
926 	char *pDest;
927 	const char *p;
928 	int old_len;
929 	int new_len;
930 	int len;
931 	int max_dest_len;
932 	int remain_len;
933 
934 	if (dest_size <= 0)
935 	{
936 		return 0;
937 	}
938 
939 	max_dest_len = dest_size - 1;
940 	old_len = strlen(replaced);
941 	new_len = strlen(new_str);
942 	if (old_len == 0)
943 	{
944 		len = src_len < max_dest_len ? src_len : max_dest_len;
945 		memcpy(dest, s, len);
946 		dest[len] = '\0';
947 		return len;
948 	}
949 
950 	remain_len = max_dest_len;
951 	pDest = dest;
952 	pStart = s;
953 	pEnd = s + src_len;
954 	while (1)
955 	{
956 		p = strstr(pStart, replaced);
957 		if (p == NULL)
958 		{
959 			break;
960 		}
961 
962 		len = p - pStart;
963 		if (len > 0)
964 		{
965 			if (len < remain_len)
966 			{
967 				memcpy(pDest, pStart, len);
968 				pDest += len;
969 				remain_len -= len;
970 			}
971 			else
972 			{
973 				memcpy(pDest, pStart, remain_len);
974 				pDest += remain_len;
975 				*pDest = '\0';
976 				return pDest - dest;
977 			}
978 		}
979 
980 		if (new_len < remain_len)
981 		{
982 			memcpy(pDest, new_str, new_len);
983 			pDest += new_len;
984 			remain_len -= new_len;
985 		}
986 		else
987 		{
988 			memcpy(pDest, new_str, remain_len);
989 			pDest += remain_len;
990 			*pDest = '\0';
991 			return pDest - dest;
992 		}
993 
994 		pStart = p + old_len;
995 	}
996 
997 	len = pEnd - pStart;
998 	if (len > 0)
999 	{
1000 		if (len > remain_len)
1001 		{
1002 			len = remain_len;
1003 		}
1004 		memcpy(pDest, pStart, len);
1005 		pDest += len;
1006 	}
1007 	*pDest = '\0';
1008 	return pDest - dest;
1009 }
1010 
fileExists(const char * filename)1011 bool fileExists(const char *filename)
1012 {
1013 	return access(filename, 0) == 0;
1014 }
1015 
isDir(const char * filename)1016 bool isDir(const char *filename)
1017 {
1018 	struct stat buf;
1019 	if (stat(filename, &buf) != 0)
1020 	{
1021 		return false;
1022 	}
1023 
1024 	return S_ISDIR(buf.st_mode);
1025 }
1026 
isFile(const char * filename)1027 bool isFile(const char *filename)
1028 {
1029 	struct stat buf;
1030 	if (stat(filename, &buf) != 0)
1031 	{
1032 		return false;
1033 	}
1034 
1035 	return S_ISREG(buf.st_mode);
1036 }
1037 
chopPath(char * filePath)1038 void chopPath(char *filePath)
1039 {
1040 	int lastIndex;
1041 	if (*filePath == '\0')
1042 	{
1043 		return;
1044 	}
1045 
1046 	lastIndex = strlen(filePath) - 1;
1047 	if (filePath[lastIndex] == '/')
1048 	{
1049 		filePath[lastIndex] = '\0';
1050 	}
1051 }
1052 
getFileContent(const char * filename,char ** buff,int64_t * file_size)1053 int getFileContent(const char *filename, char **buff, int64_t *file_size)
1054 {
1055 	int fd;
1056 
1057     errno = 0;
1058     if (!isFile(filename))
1059     {
1060 		*buff = NULL;
1061 		*file_size = 0;
1062         if (errno != 0)
1063         {
1064             if (errno == ENOENT)
1065             {
1066                 logError("file: "__FILE__", line: %d, "
1067                         "file %s not exist", __LINE__, filename);
1068             }
1069             else
1070             {
1071                 logError("file: "__FILE__", line: %d, "
1072                         "stat %s fail, errno: %d, error info: %s",
1073                         __LINE__, filename, errno, STRERROR(errno));
1074             }
1075             return errno != 0 ? errno : ENOENT;
1076         }
1077         else
1078         {
1079             logError("file: "__FILE__", line: %d, "
1080                     "%s is not a regular file", __LINE__, filename);
1081             return EINVAL;
1082         }
1083     }
1084 
1085 	fd = open(filename, O_RDONLY);
1086 	if (fd < 0)
1087 	{
1088 		*buff = NULL;
1089 		*file_size = 0;
1090 		logError("file: "__FILE__", line: %d, " \
1091 			"open file %s fail, " \
1092 			"errno: %d, error info: %s", __LINE__, \
1093 			filename, errno, STRERROR(errno));
1094 		return errno != 0 ? errno : ENOENT;
1095 	}
1096 
1097 	if ((*file_size=lseek(fd, 0, SEEK_END)) < 0)
1098 	{
1099 		*buff = NULL;
1100 		*file_size = 0;
1101 		close(fd);
1102 		logError("file: "__FILE__", line: %d, " \
1103 			"lseek file %s fail, " \
1104 			"errno: %d, error info: %s", __LINE__, \
1105 			filename, errno, STRERROR(errno));
1106 		return errno != 0 ? errno : EIO;
1107 	}
1108 
1109 	*buff = (char *)malloc(*file_size + 1);
1110 	if (*buff == NULL)
1111 	{
1112 		*file_size = 0;
1113 		close(fd);
1114 
1115 		logError("file: "__FILE__", line: %d, " \
1116 			"malloc %d bytes fail", __LINE__, \
1117 			(int)(*file_size + 1));
1118 		return errno != 0 ? errno : ENOMEM;
1119 	}
1120 
1121 	if (lseek(fd, 0, SEEK_SET) < 0)
1122 	{
1123 		*buff = NULL;
1124 		*file_size = 0;
1125 		close(fd);
1126 		logError("file: "__FILE__", line: %d, " \
1127 			"lseek file %s fail, " \
1128 			"errno: %d, error info: %s", __LINE__, \
1129 			filename, errno, STRERROR(errno));
1130 		return errno != 0 ? errno : EIO;
1131 	}
1132 	if (read(fd, *buff, *file_size) != *file_size)
1133 	{
1134 		free(*buff);
1135 		*buff = NULL;
1136 		*file_size = 0;
1137 		close(fd);
1138 		logError("file: "__FILE__", line: %d, " \
1139 			"read from file %s fail, " \
1140 			"errno: %d, error info: %s", __LINE__, \
1141 			filename, errno, STRERROR(errno));
1142 		return errno != 0 ? errno : EIO;
1143 	}
1144 
1145 	(*buff)[*file_size] = '\0';
1146 	close(fd);
1147 
1148 	return 0;
1149 }
1150 
getFileContentEx(const char * filename,char * buff,int64_t offset,int64_t * size)1151 int getFileContentEx(const char *filename, char *buff, \
1152 		int64_t offset, int64_t *size)
1153 {
1154 	int fd;
1155 	int read_bytes;
1156 
1157 	if (*size <= 0)
1158 	{
1159 		logError("file: "__FILE__", line: %d, " \
1160 			"invalid size: %"PRId64, \
1161 			__LINE__, *size);
1162 		return EINVAL;
1163 	}
1164 
1165 	fd = open(filename, O_RDONLY);
1166 	if (fd < 0)
1167 	{
1168 		*size = 0;
1169 		logError("file: "__FILE__", line: %d, " \
1170 			"open file %s fail, " \
1171 			"errno: %d, error info: %s", __LINE__, \
1172 			filename, errno, STRERROR(errno));
1173 		return errno != 0 ? errno : ENOENT;
1174 	}
1175 
1176 	if (offset > 0 && lseek(fd, offset, SEEK_SET) < 0)
1177 	{
1178 		*size = 0;
1179 		close(fd);
1180 		logError("file: "__FILE__", line: %d, " \
1181 			"lseek file %s fail, " \
1182 			"errno: %d, error info: %s", __LINE__, \
1183 			filename, errno, STRERROR(errno));
1184 		return errno != 0 ? errno : EIO;
1185 	}
1186 
1187 	if ((read_bytes=read(fd, buff, *size - 1)) < 0)
1188 	{
1189 		*size = 0;
1190 		close(fd);
1191 		logError("file: "__FILE__", line: %d, " \
1192 			"read from file %s fail, " \
1193 			"errno: %d, error info: %s", __LINE__, \
1194 			filename, errno, STRERROR(errno));
1195 		return errno != 0 ? errno : EIO;
1196 	}
1197 
1198 	*size = read_bytes;
1199 	*(buff + (*size)) = '\0';
1200 	close(fd);
1201 
1202 	return 0;
1203 }
1204 
writeToFile(const char * filename,const char * buff,const int file_size)1205 int writeToFile(const char *filename, const char *buff, const int file_size)
1206 {
1207 	int fd;
1208 	int result;
1209 
1210 	fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
1211 	if (fd < 0)
1212 	{
1213 		result = errno != 0 ? errno : EIO;
1214 		logError("file: "__FILE__", line: %d, " \
1215 			"open file %s fail, " \
1216 			"errno: %d, error info: %s", \
1217 			__LINE__, filename, \
1218 			result, STRERROR(result));
1219 		return result;
1220 	}
1221 
1222 	if (write(fd, buff, file_size) != file_size)
1223 	{
1224 		result = errno != 0 ? errno : EIO;
1225 		logError("file: "__FILE__", line: %d, " \
1226 			"write file %s fail, " \
1227 			"errno: %d, error info: %s", \
1228 			__LINE__, filename, \
1229 			result, STRERROR(result));
1230 		close(fd);
1231 		return result;
1232 	}
1233 
1234 	if (fsync(fd) != 0)
1235 	{
1236 		result = errno != 0 ? errno : EIO;
1237 		logError("file: "__FILE__", line: %d, " \
1238 			"fsync file \"%s\" fail, " \
1239 			"errno: %d, error info: %s", \
1240 			__LINE__, filename, \
1241 			result, STRERROR(result));
1242 		close(fd);
1243 		return result;
1244 	}
1245 
1246 	close(fd);
1247 	return 0;
1248 }
1249 
safeWriteToFile(const char * filename,const char * buff,const int file_size)1250 int safeWriteToFile(const char *filename, const char *buff, \
1251 		const int file_size)
1252 {
1253 	char tmpFilename[MAX_PATH_SIZE];
1254 	int result;
1255 
1256 	snprintf(tmpFilename, sizeof(tmpFilename), "%s.tmp", filename);
1257 	if ((result=writeToFile(tmpFilename, buff, file_size)) != 0)
1258 	{
1259 		return result;
1260 	}
1261 
1262 	if (rename(tmpFilename, filename) != 0)
1263 	{
1264 		result = errno != 0 ? errno : EIO;
1265 		logError("file: "__FILE__", line: %d, " \
1266 			"rename file \"%s\" to \"%s\" fail, " \
1267 			"errno: %d, error info: %s", \
1268 			__LINE__, tmpFilename, filename, \
1269 			result, STRERROR(result));
1270 		return result;
1271 	}
1272 
1273 	return 0;
1274 }
1275 
short2buff(const short n,char * buff)1276 void short2buff(const short n, char *buff)
1277 {
1278 	unsigned char *p;
1279 	p = (unsigned char *)buff;
1280 	*p++ = (n >> 8) & 0xFF;
1281 	*p++ = n & 0xFF;
1282 }
1283 
buff2short(const char * buff)1284 short buff2short(const char *buff)
1285 {
1286 	return  (short)((((unsigned char)(*(buff))) << 8) | \
1287 		((unsigned char)(*(buff+1))));
1288 }
1289 
int2buff(const int n,char * buff)1290 void int2buff(const int n, char *buff)
1291 {
1292 	unsigned char *p;
1293 	p = (unsigned char *)buff;
1294 	*p++ = (n >> 24) & 0xFF;
1295 	*p++ = (n >> 16) & 0xFF;
1296 	*p++ = (n >> 8) & 0xFF;
1297 	*p++ = n & 0xFF;
1298 }
1299 
buff2int(const char * buff)1300 int buff2int(const char *buff)
1301 {
1302 	return  (((unsigned char)(*buff)) << 24) | \
1303 		(((unsigned char)(*(buff+1))) << 16) |  \
1304 		(((unsigned char)(*(buff+2))) << 8) | \
1305 		((unsigned char)(*(buff+3)));
1306 }
1307 
long2buff(int64_t n,char * buff)1308 void long2buff(int64_t n, char *buff)
1309 {
1310 	unsigned char *p;
1311 	p = (unsigned char *)buff;
1312 	*p++ = (n >> 56) & 0xFF;
1313 	*p++ = (n >> 48) & 0xFF;
1314 	*p++ = (n >> 40) & 0xFF;
1315 	*p++ = (n >> 32) & 0xFF;
1316 	*p++ = (n >> 24) & 0xFF;
1317 	*p++ = (n >> 16) & 0xFF;
1318 	*p++ = (n >> 8) & 0xFF;
1319 	*p++ = n & 0xFF;
1320 }
1321 
buff2long(const char * buff)1322 int64_t buff2long(const char *buff)
1323 {
1324 	unsigned char *p;
1325 	p = (unsigned char *)buff;
1326 	return  (((int64_t)(*p)) << 56) | \
1327 		(((int64_t)(*(p+1))) << 48) |  \
1328 		(((int64_t)(*(p+2))) << 40) |  \
1329 		(((int64_t)(*(p+3))) << 32) |  \
1330 		(((int64_t)(*(p+4))) << 24) |  \
1331 		(((int64_t)(*(p+5))) << 16) |  \
1332 		(((int64_t)(*(p+6))) << 8) | \
1333 		((int64_t)(*(p+7)));
1334 }
1335 
fd_gets(int fd,char * buff,const int size,int once_bytes)1336 int fd_gets(int fd, char *buff, const int size, int once_bytes)
1337 {
1338 	char *pDest;
1339 	char *p;
1340 	char *pEnd;
1341 	int read_bytes;
1342 	int remain_bytes;
1343 	int rewind_bytes;
1344 
1345 	if (once_bytes <= 0)
1346 	{
1347 		once_bytes = 1;
1348 	}
1349 
1350 	pDest = buff;
1351 	remain_bytes = size - 1;
1352 	while (remain_bytes > 0)
1353 	{
1354 		if (once_bytes > remain_bytes)
1355 		{
1356 			once_bytes = remain_bytes;
1357 		}
1358 
1359 		read_bytes = read(fd, pDest, once_bytes);
1360 		if (read_bytes < 0)
1361 		{
1362 			return -1;
1363 		}
1364 		if (read_bytes == 0)
1365 		{
1366 			break;
1367 		}
1368 
1369 		pEnd = pDest + read_bytes;
1370 		for (p=pDest; p<pEnd; p++)
1371 		{
1372 			if (*p == '\n')
1373 			{
1374 				break;
1375 			}
1376 		}
1377 
1378 		if (p < pEnd)
1379 		{
1380 			pDest = p + 1;  //find \n, skip \n
1381 			rewind_bytes = pEnd - pDest;
1382 			if (lseek(fd, -1 * rewind_bytes, SEEK_CUR) < 0)
1383 			{
1384 				return -1;
1385 			}
1386 
1387 			break;
1388 		}
1389 
1390 		pDest = pEnd;
1391 		remain_bytes -= read_bytes;
1392 	}
1393 
1394 	*pDest = '\0';
1395 	return pDest - buff;
1396 }
1397 
set_rlimit(int resource,const rlim_t value)1398 int set_rlimit(int resource, const rlim_t value)
1399 {
1400 	struct rlimit limit;
1401 
1402 	if (getrlimit(resource, &limit) != 0)
1403 	{
1404 		logError("file: "__FILE__", line: %d, " \
1405 			"call getrlimit fail, resource=%d, " \
1406 			"errno: %d, error info: %s", \
1407 			__LINE__, resource, errno, STRERROR(errno));
1408 		return errno != 0 ? errno : EPERM;
1409 	}
1410 
1411 	if (limit.rlim_cur == RLIM_INFINITY || \
1412             (value != RLIM_INFINITY && limit.rlim_cur >= value))
1413 	{
1414 		return 0;
1415 	}
1416 
1417 	limit.rlim_cur = value;
1418 	if (setrlimit(resource, &limit) != 0)
1419 	{
1420         const char *label;
1421         switch (resource)
1422         {
1423             case RLIMIT_CPU:
1424                 label = "CPU time in sec";
1425                 break;
1426             case RLIMIT_STACK:
1427                 label = "max stack size";
1428                 break;
1429             case RLIMIT_DATA:
1430                 label = "max data size";
1431                 break;
1432             case RLIMIT_FSIZE:
1433                 label = "max file size";
1434                 break;
1435             case RLIMIT_RSS:
1436                 label = "max RSS";
1437                 break;
1438             case RLIMIT_CORE:
1439                 label = "max core file size";
1440                 break;
1441             case RLIMIT_NPROC:
1442                 label = "max processes";
1443                 break;
1444             case RLIMIT_NOFILE:
1445                 label = "max open files";
1446                 break;
1447 #ifdef RLIMIT_MSGQUEUE
1448             case RLIMIT_MSGQUEUE:
1449                 label = "max bytes in msg queues";
1450                 break;
1451 #endif
1452             case RLIMIT_MEMLOCK:
1453                 label = "max locked-in-memory address space";
1454                 break;
1455             default:
1456                 label = "unkown";
1457                 break;
1458         }
1459 
1460 		logError("file: "__FILE__", line: %d, "
1461 			"call setrlimit fail, resource=%d (%s), "
1462             "old value=%"PRId64", new value=%"PRId64", "
1463 			"errno: %d, error info: %s", __LINE__, resource, label,
1464             (int64_t)limit.rlim_cur, (int64_t)value,
1465 			errno, STRERROR(errno));
1466 		return errno != 0 ? errno : EPERM;
1467 	}
1468 
1469 	return 0;
1470 }
1471 
is_filename_secure(const char * filename,const int len)1472 bool is_filename_secure(const char *filename, const int len)
1473 {
1474 	if (len < 3)
1475 	{
1476 		return true;
1477 	}
1478 
1479 	if (memcmp(filename, "../", 3) == 0)
1480 	{
1481 		return false;
1482 	}
1483 
1484 	return (strstr(filename, "/../") == NULL);
1485 }
1486 
load_log_level(IniContext * pIniContext)1487 void load_log_level(IniContext *pIniContext)
1488 {
1489 	set_log_level(iniGetStrValue(NULL, "log_level", pIniContext));
1490 }
1491 
load_log_level_ex(const char * conf_filename)1492 int load_log_level_ex(const char *conf_filename)
1493 {
1494 	int result;
1495 	IniContext iniContext;
1496 
1497 	if ((result=iniLoadFromFileEx(conf_filename, &iniContext,
1498                     FAST_INI_ANNOTATION_DISABLE, NULL, 0,
1499                     FAST_INI_FLAGS_NONE)) != 0)
1500 	{
1501 		logError("file: "__FILE__", line: %d, " \
1502 			"load conf file \"%s\" fail, ret code: %d", \
1503 			__LINE__, conf_filename, result);
1504 		return result;
1505 	}
1506 
1507 	load_log_level(&iniContext);
1508 	iniFreeContext(&iniContext);
1509 	return 0;
1510 }
1511 
set_log_level(char * pLogLevel)1512 void set_log_level(char *pLogLevel)
1513 {
1514 	if (pLogLevel != NULL)
1515 	{
1516 		toUppercase(pLogLevel);
1517 		if ( strncmp(pLogLevel, "DEBUG", 5) == 0 || \
1518 		     strcmp(pLogLevel, "LOG_DEBUG") == 0)
1519 		{
1520 			g_log_context.log_level = LOG_DEBUG;
1521 		}
1522 		else if ( strncmp(pLogLevel, "INFO", 4) == 0 || \
1523 		     strcmp(pLogLevel, "LOG_INFO") == 0)
1524 		{
1525 			g_log_context.log_level = LOG_INFO;
1526 		}
1527 		else if ( strncmp(pLogLevel, "NOTICE", 6) == 0 || \
1528 		     strcmp(pLogLevel, "LOG_NOTICE") == 0)
1529 		{
1530 			g_log_context.log_level = LOG_NOTICE;
1531 		}
1532 		else if ( strncmp(pLogLevel, "WARN", 4) == 0 || \
1533 		     strcmp(pLogLevel, "LOG_WARNING") == 0)
1534 		{
1535 			g_log_context.log_level = LOG_WARNING;
1536 		}
1537 		else if ( strncmp(pLogLevel, "ERR", 3) == 0 || \
1538 		     strcmp(pLogLevel, "LOG_ERR") == 0)
1539 		{
1540 			g_log_context.log_level = LOG_ERR;
1541 		}
1542 		else if ( strncmp(pLogLevel, "CRIT", 4) == 0 || \
1543 		     strcmp(pLogLevel, "LOG_CRIT") == 0)
1544 		{
1545 			g_log_context.log_level = LOG_CRIT;
1546 		}
1547 		else if ( strncmp(pLogLevel, "ALERT", 5) == 0 || \
1548 		     strcmp(pLogLevel, "LOG_ALERT") == 0)
1549 		{
1550 			g_log_context.log_level = LOG_ALERT;
1551 		}
1552 		else if ( strncmp(pLogLevel, "EMERG", 5) == 0 || \
1553 		     strcmp(pLogLevel, "LOG_EMERG") == 0)
1554 		{
1555 			g_log_context.log_level = LOG_EMERG;
1556 		}
1557 	}
1558 }
1559 
fcntl_add_flags(int fd,int get_cmd,int set_cmd,int adding_flags)1560 int fcntl_add_flags(int fd, int get_cmd, int set_cmd, int adding_flags)
1561 {
1562 	int flags;
1563 
1564 	flags = fcntl(fd, get_cmd, 0);
1565 	if (flags < 0)
1566 	{
1567 		logError("file: "__FILE__", line: %d, " \
1568 			"fcntl fail, errno: %d, error info: %s.", \
1569 			__LINE__, errno, STRERROR(errno));
1570 		return errno != 0 ? errno : EACCES;
1571 	}
1572 
1573 	if (fcntl(fd, set_cmd, flags | adding_flags) == -1)
1574 	{
1575 		logError("file: "__FILE__", line: %d, " \
1576 			"fcntl fail, errno: %d, error info: %s.", \
1577 			__LINE__, errno, STRERROR(errno));
1578 		return errno != 0 ? errno : EACCES;
1579 	}
1580 
1581 	return 0;
1582 }
1583 
fd_add_flags(int fd,int adding_flags)1584 int fd_add_flags(int fd, int adding_flags)
1585 {
1586     return fcntl_add_flags(fd, F_GETFL, F_SETFL, adding_flags);
1587 }
1588 
fd_set_cloexec(int fd)1589 int fd_set_cloexec(int fd)
1590 {
1591     return fcntl_add_flags(fd, F_GETFD, F_SETFD, FD_CLOEXEC);
1592 }
1593 
set_run_by(const char * group_name,const char * username)1594 int set_run_by(const char *group_name, const char *username)
1595 {
1596 #ifndef WIN32
1597 	struct group *pGroup;
1598 	struct passwd *pUser;
1599 	int nErrNo;
1600 	if (group_name != NULL && *group_name != '\0')
1601 	{
1602      		pGroup = getgrnam(group_name);
1603 		if (pGroup == NULL)
1604 		{
1605 			nErrNo = errno != 0 ? errno : ENOENT;
1606 			logError("file: "__FILE__", line: %d, " \
1607 				"getgrnam %s fail, errno: %d, error info: %s.", \
1608 				__LINE__, group_name, nErrNo, STRERROR(nErrNo));
1609 			return nErrNo;
1610 		}
1611 
1612 		if (setegid(pGroup->gr_gid) != 0)
1613 		{
1614 			nErrNo = errno != 0 ? errno : EPERM;
1615 			logError("file: "__FILE__", line: %d, " \
1616 				"setegid fail, errno: %d, error info: %s.", \
1617 				__LINE__, nErrNo, STRERROR(nErrNo));
1618 			return nErrNo;
1619 		}
1620 	}
1621 
1622 	if (username != NULL && *username != '\0')
1623 	{
1624      		pUser = getpwnam(username);
1625 		if (pUser == NULL)
1626 		{
1627 			nErrNo = errno != 0 ? errno : ENOENT;
1628 			logError("file: "__FILE__", line: %d, " \
1629 				"getpwnam %s fail, errno: %d, error info: %s.", \
1630 				__LINE__, username, nErrNo, STRERROR(nErrNo));
1631 			return nErrNo;
1632 		}
1633 
1634 		if (seteuid(pUser->pw_uid) != 0)
1635 		{
1636 			nErrNo = errno != 0 ? errno : EPERM;
1637 			logError("file: "__FILE__", line: %d, " \
1638 				"seteuid fail, errno: %d, error info: %s.", \
1639 				__LINE__, nErrNo, STRERROR(nErrNo));
1640 			return nErrNo;
1641 		}
1642 	}
1643 #endif
1644 
1645 	return 0;
1646 }
1647 
check_realloc_allow_ips(in_addr_t ** allow_ip_addrs,int * alloc_count,const int target_ip_count)1648 static int check_realloc_allow_ips(in_addr_t **allow_ip_addrs,
1649 	int *alloc_count, const int target_ip_count)
1650 {
1651 	int bytes;
1652 	if (*alloc_count < target_ip_count)
1653 	{
1654 		*alloc_count = target_ip_count;
1655 		bytes = sizeof(in_addr_t) * (*alloc_count);
1656 		*allow_ip_addrs = (in_addr_t *)realloc(*allow_ip_addrs, bytes);
1657 		if (*allow_ip_addrs == NULL)
1658 		{
1659 			logError("file: "__FILE__", line: %d, "\
1660 				"malloc %d bytes fail, " \
1661 				"errno: %d, error info: %s", \
1662 				__LINE__, bytes, errno, STRERROR(errno));
1663 
1664 			return errno != 0 ? errno : ENOMEM;
1665 		}
1666 	}
1667 
1668 	return 0;
1669 }
1670 
parse_cidr_ips(const char * ip_addr,in_addr_t ** allow_ip_addrs,int * alloc_count,int * allow_ip_count,const int remain_items)1671 static int parse_cidr_ips(const char *ip_addr, in_addr_t **allow_ip_addrs,
1672 	int *alloc_count, int *allow_ip_count, const int remain_items)
1673 {
1674 	char *pSlash;
1675 	char *pReservedEnd;
1676 	char ip_part[IP_ADDRESS_SIZE];
1677 	int ip_len;
1678 	int network_bits;
1679 	int host_bits;
1680 	int bits;
1681 	uint32_t hip;
1682 	in_addr_t nip;
1683 	int h;
1684 	int count;
1685 	int result;
1686 	struct in_addr addr;
1687 
1688 	pSlash = strchr(ip_addr, '/');
1689 	if (pSlash == NULL)
1690 	{
1691 		return EINVAL;
1692 	}
1693 
1694 	ip_len = pSlash - ip_addr;
1695 	if (ip_len == 0 || ip_len >= IP_ADDRESS_SIZE)
1696 	{
1697 		logError("file: "__FILE__", line: %d, " \
1698 			"invalid ip address: %s", \
1699 			__LINE__, ip_addr);
1700 		return EINVAL;
1701 	}
1702 	memcpy(ip_part, ip_addr, ip_len);
1703 	*(ip_part + ip_len) = '\0';
1704 
1705 	pReservedEnd = NULL;
1706 	network_bits = strtol(pSlash + 1, &pReservedEnd, 10);
1707 	if (!(pReservedEnd == NULL || *pReservedEnd == '\0'))
1708 	{
1709 		logError("file: "__FILE__", line: %d, " \
1710 			"ip address: %s, invalid network bits: %s",
1711 			__LINE__, ip_addr, pSlash + 1);
1712 		return EINVAL;
1713 	}
1714 
1715 	if (network_bits < 10 || network_bits >= 32)
1716 	{
1717 		logError("file: "__FILE__", line: %d, " \
1718 			"ip address: %s, invalid network bits: %d, " \
1719 			"it should >= 10 and < 32", \
1720 			__LINE__, ip_addr, network_bits);
1721 		return EINVAL;
1722 	}
1723 
1724 	if (inet_pton(AF_INET, ip_part, &addr) != 1)
1725 	{
1726 		logError("file: "__FILE__", line: %d, " \
1727 			"ip address: %s, invalid ip part: %s", \
1728 			__LINE__, ip_addr, ip_part);
1729 		return EINVAL;
1730 	}
1731 
1732 	host_bits = 32 - network_bits;
1733 	count = 2;
1734 	bits = host_bits;
1735 	while (--bits)
1736 	{
1737 		count *= 2;
1738 	}
1739 
1740 	if ((result=check_realloc_allow_ips(allow_ip_addrs,
1741 		alloc_count, (*allow_ip_count) + count + remain_items)) != 0)
1742 	{
1743 		return result;
1744 	}
1745 
1746 	logDebug("CIDR ip: %s, ip count: %d", ip_addr, count);
1747 
1748 	hip = ntohl(addr.s_addr);
1749 	for (h=0; h<count; h++)
1750 	{
1751 		struct sockaddr_in a;
1752 
1753 		nip = htonl(hip | h);
1754 		(*allow_ip_addrs)[*allow_ip_count] = nip;
1755 		(*allow_ip_count)++;
1756 
1757 		a.sin_addr.s_addr = nip;
1758 		if (inet_ntop(AF_INET, &a.sin_addr, ip_part, IP_ADDRESS_SIZE) != NULL)
1759 		{
1760 			logDebug("%d. %s", h + 1, ip_part);
1761 		}
1762 	}
1763 
1764 	return 0;
1765 }
1766 
parse_range_hosts(const char * value,char * pStart,char * pEnd,char * hostname,const int nHeadLen,in_addr_t ** allow_ip_addrs,int * alloc_count,int * allow_ip_count,const int remain_items)1767 static int parse_range_hosts(const char *value, char *pStart, char *pEnd,
1768 	char *hostname, const int nHeadLen, in_addr_t **allow_ip_addrs,
1769 	int *alloc_count, int *allow_ip_count, const int remain_items)
1770 {
1771 	char *pTail;
1772 	char *p;
1773 	int result;
1774 	int i;
1775 	in_addr_t addr;
1776 
1777 	pTail = pEnd + 1;
1778 	p = pStart + 1;  //skip [
1779 	while (p <= pEnd)
1780 	{
1781 		char *pNumStart1;
1782 		char *pNumStart2;
1783 		int nStart;
1784 		int nEnd;
1785 		int nNumLen1;
1786 		int nNumLen2;
1787 		char end_ch1;
1788 		char end_ch2;
1789 		char szFormat[16];
1790 
1791 		while (*p == ' ' || *p == '\t') //trim prior spaces
1792 		{
1793 			p++;
1794 		}
1795 
1796 		pNumStart1 = p;
1797 		while (*p >='0' && *p <= '9')
1798 		{
1799 			p++;
1800 		}
1801 
1802 		nNumLen1 = p - pNumStart1;
1803 		while (*p == ' ' || *p == '\t') //trim tail spaces
1804 		{
1805 			p++;
1806 		}
1807 
1808 		if (!(*p == ',' || *p == '-' || *p == ']'))
1809 		{
1810 			logError("file: "__FILE__", line: %d, " \
1811 				"invalid char \"%c\" in host name: %s",\
1812 				__LINE__, *p, value);
1813 			return EINVAL;
1814 		}
1815 
1816 		end_ch1 = *p;
1817 		*(pNumStart1 + nNumLen1) = '\0';
1818 
1819 		if (nNumLen1 == 0)
1820 		{
1821 			logError("file: "__FILE__", line: %d, " \
1822 				"invalid host name: %s, " \
1823 				"empty entry before \"%c\"", \
1824 				__LINE__, value, end_ch1);
1825 			return EINVAL;
1826 		}
1827 
1828 		nStart = atoi(pNumStart1);
1829 		if (end_ch1 == '-')
1830 		{
1831 			p++;   //skip -
1832 
1833 			/* trim prior spaces */
1834 			while (*p == ' ' || *p == '\t')
1835 			{
1836 				p++;
1837 			}
1838 
1839 			pNumStart2 = p;
1840 			while (*p >='0' && *p <= '9')
1841 			{
1842 				p++;
1843 			}
1844 
1845 			nNumLen2 = p - pNumStart2;
1846 			/* trim tail spaces */
1847 			while (*p == ' ' || *p == '\t')
1848 			{
1849 				p++;
1850 			}
1851 
1852 			if (!(*p == ',' || *p == ']'))
1853 			{
1854 				logError("file: "__FILE__", line: %d, " \
1855 					"invalid char \"%c\" in host name: %s",\
1856 					__LINE__, *p, value);
1857 				return EINVAL;
1858 			}
1859 
1860 			end_ch2 = *p;
1861 			*(pNumStart2 + nNumLen2) = '\0';
1862 
1863 			if (nNumLen2 == 0)
1864 			{
1865 				logError("file: "__FILE__", line: %d, " \
1866 					"invalid host name: %s, " \
1867 					"empty entry before \"%c\"", \
1868 					__LINE__, value, end_ch2);
1869 				return EINVAL;
1870 			}
1871 
1872 			nEnd = atoi(pNumStart2);
1873 		}
1874 		else
1875 		{
1876 			nEnd = nStart;
1877 		}
1878 
1879 
1880 		if ((result=check_realloc_allow_ips(allow_ip_addrs,
1881 			alloc_count, (*allow_ip_count) + remain_items +
1882 			(nEnd - nStart + 1))) != 0)
1883 		{
1884 			return result;
1885 		}
1886 
1887 		sprintf(szFormat, "%%0%dd%%s",  nNumLen1);
1888 		for (i=nStart; i<=nEnd; i++)
1889 		{
1890 			sprintf(hostname + nHeadLen, szFormat, \
1891 				i, pTail);
1892 
1893 			addr = getIpaddrByName(hostname, NULL, 0);
1894 			if (addr == INADDR_NONE)
1895 			{
1896 				logWarning("file: "__FILE__", line: %d, " \
1897 					"invalid host name: %s", \
1898 					__LINE__, hostname);
1899 			}
1900 			else
1901 			{
1902 				(*allow_ip_addrs)[*allow_ip_count] = addr;
1903 				(*allow_ip_count)++;
1904 			}
1905 
1906 		}
1907 
1908 		p++;
1909 	}
1910 
1911 	return 0;
1912 }
1913 
load_allow_hosts(IniContext * pIniContext,in_addr_t ** allow_ip_addrs,int * allow_ip_count)1914 int load_allow_hosts(IniContext *pIniContext, \
1915 		in_addr_t **allow_ip_addrs, int *allow_ip_count)
1916 {
1917 	int result;
1918 	int count;
1919 	IniItem *pItem;
1920 	IniItem *pItemStart;
1921 	IniItem *pItemEnd;
1922 	char item_value[256];
1923 	char *pStart;
1924 	char *pEnd;
1925 	int alloc_count;
1926 	int nHeadLen;
1927 	int nValueLen;
1928 	int i;
1929 	in_addr_t addr;
1930 	char hostname[256];
1931 
1932 	if ((pItemStart=iniGetValuesEx(NULL, "allow_hosts", \
1933 		pIniContext, &count)) == NULL)
1934 	{
1935 		*allow_ip_count = -1; /* -1 means match any ip address */
1936 		*allow_ip_addrs = NULL;
1937 		return 0;
1938 	}
1939 
1940 	pItemEnd = pItemStart + count;
1941 	for (pItem=pItemStart; pItem<pItemEnd; pItem++)
1942 	{
1943 		if (strcmp(pItem->value, "*") == 0)
1944 		{
1945 			*allow_ip_count = -1; /* -1 means match any ip address*/
1946 			*allow_ip_addrs = NULL;
1947 			return 0;
1948 		}
1949 	}
1950 
1951 	alloc_count = count;
1952 	*allow_ip_count = 0;
1953 	*allow_ip_addrs = (in_addr_t *)malloc(sizeof(in_addr_t) * alloc_count);
1954 	if (*allow_ip_addrs == NULL)
1955 	{
1956 		logError("file: "__FILE__", line: %d, " \
1957 			"malloc %d bytes fail, errno: %d, error info: %s.", \
1958 			__LINE__, (int)sizeof(in_addr_t) * alloc_count, \
1959 			errno, STRERROR(errno));
1960 		return errno != 0 ? errno : ENOMEM;
1961 	}
1962 
1963 	for (pItem=pItemStart; pItem<pItemEnd; pItem++)
1964 	{
1965 		if (*(pItem->value) == '\0')
1966 		{
1967 			continue;
1968 		}
1969 
1970 		pStart = strchr(pItem->value, '[');
1971 		if (pStart == NULL)
1972 		{
1973 			if (strchr(pItem->value, '/') != NULL) //CIDR addresses
1974 			{
1975 				if ((result=parse_cidr_ips(pItem->value,
1976 					allow_ip_addrs, &alloc_count,
1977 					allow_ip_count, pItemEnd - pItem)) != 0)
1978 				{
1979 					return result;
1980 				}
1981 				continue;
1982 			}
1983 
1984 			addr = getIpaddrByName(pItem->value, NULL, 0);
1985 			if (addr == INADDR_NONE)
1986 			{
1987 				logWarning("file: "__FILE__", line: %d, " \
1988 					"invalid host name: %s", \
1989 					__LINE__, pItem->value);
1990 			}
1991 			else
1992 			{
1993 				if ((result=check_realloc_allow_ips(allow_ip_addrs,
1994 					&alloc_count, (*allow_ip_count) + (pItemEnd - pItem))) != 0)
1995 				{
1996 					return result;
1997 				}
1998 
1999 				(*allow_ip_addrs)[*allow_ip_count] = addr;
2000 				(*allow_ip_count)++;
2001 			}
2002 
2003 			continue;
2004 		}
2005 
2006 
2007 		pEnd = strchr(pStart, ']');
2008 		if (pEnd == NULL)
2009 		{
2010 			logError("file: "__FILE__", line: %d, " \
2011 				"invalid host name: %s, expect \"]\"", \
2012 				__LINE__, pItem->value);
2013 			return EINVAL;
2014 		}
2015 
2016 		nValueLen = strlen(pItem->value);
2017 		if (nValueLen >= (int)sizeof(item_value))
2018 		{
2019 			logError("file: "__FILE__", line: %d, " \
2020 				"hostname too long, exceeds %d bytes", \
2021 				__LINE__, (int)sizeof(item_value));
2022 			return EINVAL;
2023 		}
2024 		memcpy(item_value, pItem->value, nValueLen + 1);
2025 		nHeadLen = pStart - pItem->value;
2026 		memcpy(hostname, pItem->value, nHeadLen);
2027 
2028 		result = parse_range_hosts(pItem->value, item_value + nHeadLen,
2029 				item_value + (pEnd - pItem->value),
2030 				hostname, nHeadLen, allow_ip_addrs,
2031 				&alloc_count, allow_ip_count, pItemEnd - pItem);
2032 		if (result != 0)
2033 		{
2034 			return result;
2035 		}
2036 	}
2037 
2038 	if (*allow_ip_count == 0)
2039 	{
2040 		logWarning("file: "__FILE__", line: %d, " \
2041 			"allow ip count: 0", __LINE__);
2042 	}
2043 
2044 	if (*allow_ip_count > 0)
2045 	{
2046 		qsort(*allow_ip_addrs,  *allow_ip_count, sizeof(in_addr_t), \
2047 			cmp_by_ip_addr_t);
2048 	}
2049 
2050 	logDebug("allow_ip_count=%d", *allow_ip_count);
2051 	for (i=0; i<*allow_ip_count; i++)
2052 	{
2053 		struct in_addr address;
2054         char buff[INET_ADDRSTRLEN];
2055 		address.s_addr = (*allow_ip_addrs)[i];
2056 		logDebug("%d. %s", i + 1, inet_ntop(AF_INET, &address,
2057                     buff, sizeof(buff)));
2058 	}
2059 
2060 	return 0;
2061 }
2062 
cmp_by_ip_addr_t(const void * p1,const void * p2)2063 int cmp_by_ip_addr_t(const void *p1, const void *p2)
2064 {
2065         return memcmp((in_addr_t *)p1, (in_addr_t *)p2, sizeof(in_addr_t));
2066 }
2067 
parse_bytes(char * pStr,const int default_unit_bytes,int64_t * bytes)2068 int parse_bytes(char *pStr, const int default_unit_bytes, int64_t *bytes)
2069 {
2070 	char *pReservedEnd;
2071 
2072 	pReservedEnd = NULL;
2073 	*bytes = strtol(pStr, &pReservedEnd, 10);
2074 	if (*bytes < 0)
2075 	{
2076 		logError("file: "__FILE__", line: %d, " \
2077 			"bytes: %"PRId64" < 0", __LINE__, *bytes);
2078 		return EINVAL;
2079 	}
2080 
2081 	if (pReservedEnd == NULL || *pReservedEnd == '\0')
2082 	{
2083 		*bytes *= default_unit_bytes;
2084 	}
2085 	else if (*pReservedEnd == 'G' || *pReservedEnd == 'g')
2086 	{
2087 		*bytes *= 1024 * 1024 * 1024;
2088 	}
2089 	else if (*pReservedEnd == 'M' || *pReservedEnd == 'm')
2090 	{
2091 		*bytes *= 1024 * 1024;
2092 	}
2093 	else if (*pReservedEnd == 'K' || *pReservedEnd == 'k')
2094 	{
2095 		*bytes *= 1024;
2096 	}
2097 
2098 	return 0;
2099 }
2100 
set_rand_seed()2101 int set_rand_seed()
2102 {
2103 	struct timeval tv;
2104 
2105 	if (gettimeofday(&tv, NULL) != 0)
2106 	{
2107 		logError("file: "__FILE__", line: %d, " \
2108 			 "call gettimeofday fail, " \
2109 			 "errno=%d, error info: %s", \
2110 			 __LINE__, errno, STRERROR(errno));
2111 		return errno != 0 ? errno : EPERM;
2112 	}
2113 
2114 	srand(tv.tv_sec ^ tv.tv_usec);
2115 	return 0;
2116 }
2117 
get_time_item_from_conf(IniContext * pIniContext,const char * item_name,TimeInfo * pTimeInfo,const byte default_hour,const byte default_minute)2118 int get_time_item_from_conf(IniContext *pIniContext, \
2119 		const char *item_name, TimeInfo *pTimeInfo, \
2120 		const byte default_hour, const byte default_minute)
2121 {
2122 	char *pValue;
2123 	pValue = iniGetStrValue(NULL, item_name, pIniContext);
2124     return get_time_item_from_str(pValue, item_name, pTimeInfo,
2125 		default_hour, default_minute);
2126 }
2127 
get_time_item_from_str(const char * pValue,const char * item_name,TimeInfo * pTimeInfo,const byte default_hour,const byte default_minute)2128 int get_time_item_from_str(const char *pValue, const char *item_name,
2129         TimeInfo *pTimeInfo, const byte default_hour,
2130         const byte default_minute)
2131 {
2132 	int hour;
2133 	int minute;
2134 	int second;
2135     int count;
2136 
2137 	if (pValue == NULL)
2138 	{
2139 		pTimeInfo->hour = default_hour;
2140 		pTimeInfo->minute = default_minute;
2141 		pTimeInfo->second = 0;
2142 		return 0;
2143 	}
2144 
2145     second = 0;
2146     count = sscanf(pValue, "%d:%d:%d", &hour, &minute, &second);
2147 	if (count != 2 && count != 3)
2148 	{
2149 		logError("file: "__FILE__", line: %d, " \
2150 			"item \"%s\" 's value \"%s\" is not an valid time", \
2151 			__LINE__, item_name, pValue);
2152 		return EINVAL;
2153 	}
2154 
2155 	if ((hour < 0 || hour > 23) || (minute < 0 || minute > 59)
2156              || (second < 0 || second > 59))
2157 	{
2158 		logError("file: "__FILE__", line: %d, " \
2159 			"item \"%s\" 's value \"%s\" is not an valid time", \
2160 			__LINE__, item_name, pValue);
2161 		return EINVAL;
2162 	}
2163 
2164 	pTimeInfo->hour = (byte)hour;
2165 	pTimeInfo->minute = (byte)minute;
2166 	pTimeInfo->second = (byte)second;
2167 
2168 	return 0;
2169 }
2170 
urlencode(const char * src,const int src_len,char * dest,int * dest_len)2171 char *urlencode(const char *src, const int src_len, char *dest, int *dest_len)
2172 {
2173 	static unsigned char hex_chars[] = "0123456789ABCDEF";
2174 	const unsigned char *pSrc;
2175 	const unsigned char *pEnd;
2176 	char *pDest;
2177 
2178 	pDest = dest;
2179 	pEnd = (unsigned char *)src + src_len;
2180 	for (pSrc=(unsigned char *)src; pSrc<pEnd; pSrc++)
2181 	{
2182 		if ((*pSrc >= '0' && *pSrc <= '9') ||
2183 	 	    (*pSrc >= 'a' && *pSrc <= 'z') ||
2184 	 	    (*pSrc >= 'A' && *pSrc <= 'Z') ||
2185 		    (*pSrc == '_' || *pSrc == '-' || *pSrc == '.'))
2186 		{
2187 			*pDest++ = *pSrc;
2188 		}
2189 		else if (*pSrc == ' ')
2190 		{
2191 			*pDest++ = '+';
2192 		}
2193 		else
2194 		{
2195 			*pDest++ = '%';
2196 			*pDest++ = hex_chars[(*pSrc) >> 4];
2197 			*pDest++ = hex_chars[(*pSrc) & 0x0F];
2198 		}
2199 	}
2200 
2201 	*pDest = '\0';
2202 	*dest_len = pDest - dest;
2203 
2204 	return dest;
2205 }
2206 
urldecode(const char * src,const int src_len,char * dest,int * dest_len)2207 char *urldecode(const char *src, const int src_len, char *dest, int *dest_len)
2208 {
2209     (void)urldecode_ex(src, src_len, dest, dest_len);
2210     *(dest + *dest_len) = '\0';
2211     return dest;
2212 }
2213 
urldecode_ex(const char * src,const int src_len,char * dest,int * dest_len)2214 char *urldecode_ex(const char *src, const int src_len, char *dest, int *dest_len)
2215 {
2216 #define HEX_VALUE(ch, value) \
2217 	if (ch >= '0' && ch <= '9') \
2218 	{ \
2219 		value = ch - '0'; \
2220 	} \
2221 	else if (ch >= 'a' && ch <= 'f') \
2222 	{ \
2223 		value = ch - 'a' + 10; \
2224 	} \
2225 	else \
2226 	{ \
2227 		value = ch - 'A' + 10; \
2228 	}
2229 
2230 	const unsigned char *pSrc;
2231 	const unsigned char *pEnd;
2232 	char *pDest;
2233 	unsigned char cHigh;
2234 	unsigned char cLow;
2235 	int valHigh;
2236 	int valLow;
2237 
2238 	pDest = dest;
2239 	pSrc = (unsigned char *)src;
2240 	pEnd = (unsigned char *)src + src_len;
2241 	while (pSrc < pEnd)
2242 	{
2243 		if (*pSrc == '%' && pSrc + 2 < pEnd)
2244 		{
2245 			cHigh = *(pSrc + 1);
2246 			cLow = *(pSrc + 2);
2247 
2248 			if (IS_HEX_CHAR(cHigh) && IS_HEX_CHAR(cLow))
2249 			{
2250 				HEX_VALUE(cHigh, valHigh)
2251 				HEX_VALUE(cLow, valLow)
2252 				*pDest++ = (valHigh << 4) | valLow;
2253 				pSrc += 3;
2254 			}
2255 			else
2256 			{
2257 				*pDest++ = *pSrc;
2258 				pSrc++;
2259 			}
2260 		}
2261 		else if (*pSrc == '+')
2262 		{
2263 			*pDest++ = ' ';
2264 			pSrc++;
2265 		}
2266 		else
2267 		{
2268 			*pDest++ = *pSrc;
2269 			pSrc++;
2270 		}
2271 	}
2272 
2273 	*dest_len = pDest - dest;
2274 	return dest;
2275 }
2276 
buffer_strcpy(BufferInfo * pBuff,const char * str)2277 int buffer_strcpy(BufferInfo *pBuff, const char *str)
2278 {
2279 	pBuff->length = strlen(str);
2280 	if (pBuff->alloc_size <= pBuff->length)
2281 	{
2282 		if (pBuff->buff != NULL)
2283 		{
2284 			free(pBuff->buff);
2285 		}
2286 
2287 		pBuff->alloc_size = pBuff->length + 1;
2288 		pBuff->buff = (char *)malloc(pBuff->alloc_size);
2289 		if (pBuff->buff == NULL)
2290 		{
2291 			logError("file: "__FILE__", line: %d, " \
2292 				"malloc %d bytes fail, " \
2293 				"errno: %d, error info: %s", \
2294 				__LINE__, pBuff->alloc_size, \
2295 				errno, STRERROR(errno));
2296 			pBuff->alloc_size = 0;
2297 			return errno != 0 ? errno : ENOMEM;
2298 		}
2299 	}
2300 
2301 	memcpy(pBuff->buff, str, pBuff->length + 1);
2302 	return 0;
2303 }
2304 
buffer_memcpy(BufferInfo * pBuff,const char * buff,const int len)2305 int buffer_memcpy(BufferInfo *pBuff, const char *buff, const int len)
2306 {
2307 	pBuff->length = len;
2308 	if (pBuff->alloc_size <= pBuff->length)
2309 	{
2310 		if (pBuff->buff != NULL)
2311 		{
2312 			free(pBuff->buff);
2313 		}
2314 
2315 		pBuff->alloc_size = pBuff->length;
2316 		pBuff->buff = (char *)malloc(pBuff->alloc_size);
2317 		if (pBuff->buff == NULL)
2318 		{
2319 			logError("file: "__FILE__", line: %d, " \
2320 				"malloc %d bytes fail, " \
2321 				"errno: %d, error info: %s", \
2322 				__LINE__, pBuff->alloc_size, \
2323 				errno, STRERROR(errno));
2324 			pBuff->alloc_size = 0;
2325 			return errno != 0 ? errno : ENOMEM;
2326 		}
2327 	}
2328 
2329 	memcpy(pBuff->buff, buff, pBuff->length);
2330 	return 0;
2331 }
2332 
set_timer(const int first_remain_seconds,const int interval,void (* sighandler)(int))2333 int set_timer(const int first_remain_seconds, const int interval, \
2334 		void (*sighandler)(int))
2335 {
2336 	struct itimerval value;
2337 	struct sigaction act;
2338 
2339 	memset(&act, 0, sizeof(act));
2340 	sigemptyset(&act.sa_mask);
2341 	act.sa_handler = sighandler;
2342 	if(sigaction(SIGALRM, &act, NULL) < 0)
2343 	{
2344 		logError("file: "__FILE__", line: %d, " \
2345 			"call sigaction fail, errno: %d, error info: %s", \
2346 			__LINE__, errno, STRERROR(errno));
2347 		return errno != 0 ? errno : EINVAL;
2348 	}
2349 
2350 	memset(&value, 0, sizeof(value));
2351 	value.it_interval.tv_sec = interval;
2352 	value.it_value.tv_sec = first_remain_seconds;
2353 	if (setitimer(ITIMER_REAL, &value, NULL) < 0)
2354 	{
2355 		logError("file: "__FILE__", line: %d, " \
2356 			"call setitimer fail, errno: %d, error info: %s", \
2357 			__LINE__, errno, STRERROR(errno));
2358 		return errno != 0 ? errno : EINVAL;
2359 	}
2360 
2361 	return 0;
2362 }
2363 
set_file_utimes(const char * filename,const time_t new_time)2364 int set_file_utimes(const char *filename, const time_t new_time)
2365 {
2366 	struct timeval tvs[2];
2367 
2368 	tvs[0].tv_sec = new_time;
2369 	tvs[0].tv_usec = 0;
2370 	tvs[1].tv_sec = new_time;
2371 	tvs[1].tv_usec = 0;
2372 	if (utimes(filename, tvs) != 0)
2373 	{
2374 		logWarning("file: "__FILE__", line: %d, " \
2375 			"call utimes file: %s fail" \
2376 			", errno: %d, error info: %s", \
2377 			__LINE__, filename, errno, STRERROR(errno));
2378 		return errno != 0 ? errno : ENOENT;
2379 	}
2380 
2381 	return 0;
2382 }
2383 
ignore_signal_pipe()2384 int ignore_signal_pipe()
2385 {
2386 	struct sigaction act;
2387 
2388 	memset(&act, 0, sizeof(act));
2389 	sigemptyset(&act.sa_mask);
2390 	act.sa_handler = SIG_IGN;
2391 	if(sigaction(SIGPIPE, &act, NULL) < 0)
2392 	{
2393 		logError("file: "__FILE__", line: %d, " \
2394 			"call sigaction fail, errno: %d, error info: %s", \
2395 			__LINE__, errno, STRERROR(errno));
2396 		return errno;
2397 	}
2398 
2399 	return 0;
2400 }
2401 
get_line_distance_km(const double lat1,const double lon1,const double lat2,const double lon2)2402 double get_line_distance_km(const double lat1, const double lon1,
2403         const double lat2, const double lon2)
2404 {
2405 #define FAST_ABS(v) ((v) >= 0 ? (v) : -1 * (v))
2406 #define DISTANCE_PER_LATITUDE 111.111
2407 
2408     double lat_value;
2409     double lng_distance;
2410     double lat_distance;
2411 
2412     lat_value = FAST_ABS(lat1) < FAST_ABS(lat2) ? lat1 : lat2;
2413     lat_distance = FAST_ABS(lat1 - lat2) * DISTANCE_PER_LATITUDE;
2414     lng_distance = FAST_ABS(lon1 - lon2) * DISTANCE_PER_LATITUDE *
2415         cos(lat_value * 3.1415926 / 180.0);
2416 
2417     return sqrt(lat_distance * lat_distance + lng_distance * lng_distance);
2418 }
2419 
is_private_ip(const char * ip)2420 bool is_private_ip(const char* ip)
2421 {
2422     if (ip == NULL || (int)strlen(ip) < 8)
2423     {
2424         return false;
2425     }
2426 
2427     if (memcmp(ip, "10.", 3) == 0 || memcmp(ip, "192.168.", 8) == 0)
2428     {
2429         return true;
2430     }
2431     if (memcmp(ip, "172.", 4) == 0)
2432     {
2433         int b;
2434         b = atoi(ip + 4);
2435         if (b >= 16 && b < 32)
2436         {
2437             return true;
2438         }
2439     }
2440 
2441     return false;
2442 }
2443 
get_current_time_us()2444 int64_t get_current_time_us()
2445 {
2446 	struct timeval tv;
2447 
2448 	if (gettimeofday(&tv, NULL) != 0)
2449 	{
2450 		logError("file: "__FILE__", line: %d, " \
2451 			 "call gettimeofday fail, " \
2452 			 "errno: %d, error info: %s", \
2453 			 __LINE__, errno, STRERROR(errno));
2454 		return errno != 0 ? errno : EPERM;
2455 	}
2456 
2457 	return ((int64_t)tv.tv_sec * 1000 * 1000 + (int64_t)tv.tv_usec);
2458 }
2459 
is_power2(const int64_t n)2460 inline bool is_power2(const int64_t n)
2461 {
2462     return ((n != 0) && !(n & (n - 1)));
2463 }
2464 
do_lock_file(int fd,int cmd,int type)2465 static inline int do_lock_file(int fd, int cmd, int type)
2466 {
2467     struct flock lock;
2468     int result;
2469 
2470     memset(&lock, 0, sizeof(lock));
2471     lock.l_type = type;
2472     lock.l_whence = SEEK_SET;
2473     do
2474     {
2475         if ((result=fcntl(fd, cmd, &lock)) != 0)
2476         {
2477             result = errno != 0 ? errno : ENOMEM;
2478             fprintf(stderr, "call fcntl fail, "
2479                    "errno: %d, error info: %s\n",
2480                    result, STRERROR(result));
2481         }
2482     } while (result == EINTR);
2483 
2484     return result;
2485 }
2486 
file_read_lock(int fd)2487 int file_read_lock(int fd)
2488 {
2489     return do_lock_file(fd, F_SETLKW, F_RDLCK);
2490 }
2491 
file_write_lock(int fd)2492 int file_write_lock(int fd)
2493 {
2494     return do_lock_file(fd, F_SETLKW, F_WRLCK);
2495 }
2496 
file_unlock(int fd)2497 int file_unlock(int fd)
2498 {
2499     return do_lock_file(fd, F_SETLKW, F_UNLCK);
2500 }
2501 
file_try_read_lock(int fd)2502 int file_try_read_lock(int fd)
2503 {
2504     return do_lock_file(fd, F_SETLK, F_RDLCK);
2505 }
2506 
file_try_write_lock(int fd)2507 int file_try_write_lock(int fd)
2508 {
2509     return do_lock_file(fd, F_SETLK, F_WRLCK);
2510 }
2511 
file_try_unlock(int fd)2512 int file_try_unlock(int fd)
2513 {
2514     return do_lock_file(fd, F_SETLK, F_UNLCK);
2515 }
2516 
isLeadingSpacesLine(const char * content,const char * current)2517 bool isLeadingSpacesLine(const char *content, const char *current)
2518 {
2519     const char *p;
2520     p = current - 1;
2521     while (p >= content)
2522     {
2523         if (!(*p == ' ' || *p == '\t'))
2524         {
2525             break;
2526         }
2527         --p;
2528     }
2529     return (p < content || *p == '\n');
2530 }
2531 
isTrailingSpacesLine(const char * tail,const char * end)2532 bool isTrailingSpacesLine(const char *tail, const char *end)
2533 {
2534     const char *p;
2535     p = tail;
2536     while (p < end)
2537     {
2538         if (!(*p == ' ' || *p == '\t'))
2539         {
2540             break;
2541         }
2542         ++p;
2543     }
2544     return (p == end || *p == '\n');
2545 }
2546 
fc_safe_write(int fd,const char * buf,const size_t nbyte)2547 ssize_t fc_safe_write(int fd, const char *buf, const size_t nbyte)
2548 {
2549     ssize_t n;
2550     ssize_t remain;
2551     const char *p;
2552 
2553     n = write(fd, buf, nbyte);
2554     if (n < 0)
2555     {
2556         if (errno != EINTR)
2557         {
2558             return -1;
2559         }
2560         n = 0;
2561     }
2562     else if (n == nbyte)
2563     {
2564         return nbyte;
2565     }
2566 
2567     p = buf + n;
2568     remain = nbyte - n;
2569     while (remain > 0)
2570     {
2571         n = write(fd, p, remain);
2572         if (n < 0)
2573         {
2574             ssize_t written;
2575             if (errno == EINTR)
2576             {
2577                 continue;
2578             }
2579 
2580             written = nbyte - remain;
2581             return written > 0 ? written : -1;
2582         }
2583 
2584         p += n;
2585         remain -= n;
2586     }
2587 
2588     return nbyte;
2589 }
2590 
fc_lock_write(int fd,const char * buf,const size_t nbyte)2591 ssize_t fc_lock_write(int fd, const char *buf, const size_t nbyte)
2592 {
2593     int lock_result;
2594     ssize_t result;
2595 
2596     lock_result = file_write_lock(fd);
2597     result = fc_safe_write(fd, buf, nbyte);
2598     if (lock_result == 0)
2599     {
2600         file_unlock(fd);
2601     }
2602 
2603     return result;
2604 }
2605 
fc_safe_read(int fd,char * buf,const size_t count)2606 ssize_t fc_safe_read(int fd, char *buf, const size_t count)
2607 {
2608     ssize_t n;
2609     ssize_t remain;
2610     char *p;
2611 
2612     n = read(fd, buf, count);
2613     if (n < 0)
2614     {
2615         if (errno != EINTR)
2616         {
2617             return -1;
2618         }
2619         n = 0;
2620     }
2621     else
2622     {
2623         if (n == 0 || n == count)
2624         {
2625             return n;
2626         }
2627     }
2628 
2629     p = buf + n;
2630     remain = count - n;
2631     while (remain > 0)
2632     {
2633         n = read(fd, p, remain);
2634         if (n < 0)
2635         {
2636             ssize_t done;
2637             if (errno == EINTR)
2638             {
2639                 continue;
2640             }
2641 
2642             done = count - remain;
2643             return done > 0 ? done : -1;
2644         }
2645         else if (n == 0)
2646         {
2647             break;
2648         }
2649 
2650         p += n;
2651         remain -= n;
2652     }
2653 
2654     return count - remain;
2655 }
2656 
fc_ftok(const char * path,const int proj_id)2657 key_t fc_ftok(const char *path, const int proj_id)
2658 {
2659     int hash_code;
2660     hash_code = simple_hash(path, strlen(path));
2661     return (((proj_id & 0xFF) << 24) | (hash_code & 0xFFFFFF));
2662 }
2663 
add_thousands_separator(char * str,const int len)2664 static void add_thousands_separator(char *str, const int len)
2665 {
2666     int new_len;
2667     int addings;
2668     int sub;
2669     int chars;
2670     int add_count;
2671     char *src;
2672     char *dest;
2673     char *first;
2674 
2675     if (len <= 3)
2676     {
2677         return;
2678     }
2679 
2680     if (*str == '-')
2681     {
2682         first = str + 1;
2683         sub = 2;
2684     }
2685     else
2686     {
2687         first = str;
2688         sub = 1;
2689     }
2690 
2691     addings = (len - sub) / 3;
2692     new_len = len + addings;
2693 
2694     src = str + (len - 1);
2695     dest = str + new_len;
2696     *dest-- = '\0';
2697     chars = 0;
2698     add_count = 0;
2699     while (src >= first)
2700     {
2701         *dest-- = *src--;
2702         if (++chars % 3 == 0)
2703         {
2704             if (add_count == addings)
2705             {
2706                 break;
2707             }
2708 
2709             *dest-- = ',';
2710             add_count++;
2711         }
2712     }
2713 }
2714 
int2str(const int n,char * buff,const bool thousands_separator)2715 const char *int2str(const int n, char *buff, const bool thousands_separator)
2716 {
2717     int len;
2718     len = sprintf(buff, "%d", n);
2719     if (thousands_separator)
2720     {
2721         add_thousands_separator(buff, len);
2722     }
2723     return buff;
2724 }
2725 
long2str(const int64_t n,char * buff,const bool thousands_separator)2726 const char *long2str(const int64_t n, char *buff, const bool thousands_separator)
2727 {
2728     int len;
2729     len = sprintf(buff, "%"PRId64, n);
2730     if (thousands_separator)
2731     {
2732         add_thousands_separator(buff, len);
2733     }
2734     return buff;
2735 }
2736 
starts_with(const char * str,const char * needle)2737 bool starts_with(const char *str, const char *needle)
2738 {
2739     int str_len;
2740     int needle_len;
2741 
2742     str_len = strlen(str);
2743     needle_len = strlen(needle);
2744     if (needle_len > str_len) {
2745         return false;
2746     }
2747 
2748     return memcmp(str, needle, needle_len) == 0;
2749 }
2750 
ends_with(const char * str,const char * needle)2751 bool ends_with(const char *str, const char *needle)
2752 {
2753     int str_len;
2754     int needle_len;
2755     int start_offset;
2756 
2757     str_len = strlen(str);
2758     needle_len = strlen(needle);
2759     start_offset = str_len - needle_len;
2760     if (start_offset < 0) {
2761         return false;
2762     }
2763 
2764     return memcmp(str + start_offset, needle, needle_len) == 0;
2765 }
2766 
fc_strdup(const char * str,const int len)2767 char *fc_strdup(const char *str, const int len)
2768 {
2769     char *output;
2770 
2771     output = (char *)malloc(len + 1);
2772     if (output == NULL) {
2773         logError("file: "__FILE__", line: %d, "
2774                 "malloc %d bytes fail",
2775                 __LINE__, len + 1);
2776         return NULL;
2777     }
2778 
2779     if (len > 0) {
2780         memcpy(output, str, len);
2781     }
2782     *(output + len) = '\0';
2783     return output;
2784 }
2785 
fc_memmem(const string_t * str,const string_t * needle)2786 const char *fc_memmem(const string_t *str, const string_t *needle)
2787 {
2788     const char *ps;
2789     const char *last;
2790     const char *pn;
2791     const char *nend;
2792     int loop;
2793     int i;
2794 
2795     loop = str->len - needle->len;
2796     if (loop < 0) {
2797         return NULL;
2798     }
2799 
2800     last = str->str + loop;
2801     nend = needle->str + needle->len;
2802     for (ps=str->str; ps<=last; ps++) {
2803         for (pn=needle->str,i=0; pn<nend; pn++,i++) {
2804             if (*pn != *(ps + i)) {
2805                 break;
2806             }
2807         }
2808         if (pn == nend) {
2809             return ps;
2810         }
2811     }
2812 
2813     return NULL;
2814 }
2815 
format_http_date(time_t t,BufferInfo * buffer)2816 char *format_http_date(time_t t, BufferInfo *buffer)
2817 {
2818     struct tm tm_info;
2819 
2820     gmtime_r(&t, &tm_info);
2821     buffer->length = strftime(buffer->buff, buffer->alloc_size,
2822             "%a, %d %b %Y %H:%M:%S GMT", &tm_info);
2823     return buffer->buff;
2824 }
2825 
resolve_path(const char * from,const char * filename,char * full_filename,const int size)2826 char *resolve_path(const char *from, const char *filename,
2827         char *full_filename, const int size)
2828 {
2829     const char *last;
2830     int len;
2831 
2832     if (*filename == '/') {
2833         snprintf(full_filename, size, "%s", filename);
2834         return full_filename;
2835     }
2836 
2837     last = strrchr(from, '/');
2838     if (last != NULL) {
2839         len = last - from;
2840         snprintf(full_filename, size, "%.*s/%s", len, from, filename);
2841     } else {
2842 		logWarning("file: "__FILE__", line: %d, "
2843                 "no \"/\" in the from filename: %s",
2844                 __LINE__, from);
2845         snprintf(full_filename, size, "%s", filename);
2846     }
2847     return full_filename;
2848 }
2849 
get_gzip_command_filename()2850 const char *get_gzip_command_filename()
2851 {
2852     if (access("/usr/bin/gzip", F_OK) == 0)
2853     {
2854         return "/usr/bin/gzip";
2855     }
2856     else if (access("/bin/gzip", F_OK) == 0)
2857     {
2858         return "/bin/gzip";
2859     }
2860     else if (access("/usr/local/bin/gzip", F_OK) == 0)
2861     {
2862         return "/usr/local/bin/gzip";
2863     }
2864     else
2865     {
2866         return "gzip";
2867     }
2868 }
2869 
fc_delete_file_ex(const char * filename,const char * caption)2870 int fc_delete_file_ex(const char *filename, const char *caption)
2871 {
2872     int result;
2873 
2874     if (unlink(filename) == 0)
2875     {
2876         return 0;
2877     }
2878 
2879     result = errno != 0 ? errno : ENOENT;
2880     if (result == ENOENT)
2881     {
2882         result = 0;
2883     }
2884     else
2885     {
2886         logError("file: "__FILE__", line: %d, "
2887                 "unlink %s file: %s fail, "
2888                 "errno: %d, error info: %s",
2889                 __LINE__, caption, filename,
2890                 result, STRERROR(result));
2891     }
2892 
2893     return result;
2894 }
2895