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