/** * Copyright (C) 2008 Happy Fish / YuQing * * FastDFS may be copied only under the terms of the GNU General * Public License V3, which may be found in the FastDFS source kit. * Please visit the FastDFS Home Page http://www.csource.org/ for more detail. **/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "shared_func.h" #include "logger.h" #include "sockopt.h" char *formatDatetime(const time_t nTime, \ const char *szDateFormat, \ char *buff, const int buff_size) { static char szDateBuff[128]; struct tm tmTime; int size; localtime_r(&nTime, &tmTime); if (buff == NULL) { buff = szDateBuff; size = sizeof(szDateBuff); } else { size = buff_size; } *buff = '\0'; strftime(buff, size, szDateFormat, &tmTime); return buff; } int getCharLen(const char *s) { unsigned char *p; int count = 0; p = (unsigned char *)s; while (*p != '\0') { if (*p > 127) { if (*(++p) != '\0') { p++; } } else { p++; } count++; } return count; } char *replaceCRLF2Space(char *s) { char *p = s; while (*p != '\0') { if (*p == '\r' || *p == '\n') { *p = ' '; } p++; } return s; } char *getAbsolutePath(const char *filename, char *szAbsPath, \ const int pathSize) { char *p; int nPathLen; char szPath[1024]; char cwd[256]; p = strrchr(filename, '/'); if (p == NULL) { szPath[0] = '\0'; } else { nPathLen = p - filename; if (nPathLen >= sizeof(szPath)) { logError("file: "__FILE__", line: %d, " \ "filename length: %d is too long, exceeds %d",\ __LINE__, nPathLen, (int)sizeof(szPath)); return NULL; } memcpy(szPath, filename, nPathLen); szPath[nPathLen] = '\0'; } if (szPath[0] == '/') { snprintf(szAbsPath, pathSize, "%s", szPath); } else { if (getcwd(cwd, sizeof(cwd)) == NULL) { logError("file: "__FILE__", line: %d, " \ "call getcwd fail, errno: %d, error info: %s", \ __LINE__, errno, STRERROR(errno)); return NULL; } nPathLen = strlen(cwd); if (cwd[nPathLen - 1] == '/') { cwd[nPathLen - 1] = '\0'; } if (szPath[0] != '\0') { snprintf(szAbsPath, pathSize, "%s/%s", cwd, szPath); } else { snprintf(szAbsPath, pathSize, "%s", cwd); } } return szAbsPath; } char *getExeAbsoluteFilename(const char *exeFilename, char *szAbsFilename, \ const int maxSize) { const char *filename; const char *p; int nFileLen; int nPathLen; char cwd[256]; char szPath[1024]; nFileLen = strlen(exeFilename); if (nFileLen >= sizeof(szPath)) { logError("file: "__FILE__", line: %d, " \ "filename length: %d is too long, exceeds %d!", \ __LINE__, nFileLen, (int)sizeof(szPath)); return NULL; } p = strrchr(exeFilename, '/'); if (p == NULL) { int i; char *search_paths[] = {"/bin", "/usr/bin", "/usr/local/bin"}; *szPath = '\0'; filename = exeFilename; for (i=0; i<3; i++) { snprintf(cwd, sizeof(cwd), "%s/%s", \ search_paths[i], filename); if (fileExists(cwd)) { strcpy(szPath, search_paths[i]); break; } } if (*szPath == '\0') { if (!fileExists(filename)) { logError("file: "__FILE__", line: %d, " \ "can't find exe file %s!", __LINE__, \ filename); return NULL; } } else { snprintf(szAbsFilename, maxSize, "%s/%s", \ szPath, filename); return szAbsFilename; } } else { filename = p + 1; nPathLen = p - exeFilename; memcpy(szPath, exeFilename, nPathLen); szPath[nPathLen] = '\0'; } if (*szPath == '/') { snprintf(szAbsFilename, maxSize, "%s/%s", szPath, filename); } else { if (getcwd(cwd, sizeof(cwd)) == NULL) { logError("file: "__FILE__", line: %d, " \ "call getcwd fail, errno: %d, error info: %s", \ __LINE__, errno, STRERROR(errno)); return NULL; } nPathLen = strlen(cwd); if (cwd[nPathLen - 1] == '/') { cwd[nPathLen - 1] = '\0'; } if (*szPath != '\0') { snprintf(szAbsFilename, maxSize, "%s/%s/%s", \ cwd, szPath, filename); } else { snprintf(szAbsFilename, maxSize, "%s/%s", \ cwd, filename); } } return szAbsFilename; } #ifndef WIN32 int getProccessCount(const char *progName, const bool bAllOwners) { int *pids = NULL; return getUserProcIds(progName, bAllOwners, pids, 0); } int getUserProcIds(const char *progName, const bool bAllOwners, \ int pids[], const int arrSize) { char path[128]="/proc"; char fullpath[128]; struct stat statbuf; struct dirent *dirp; DIR *dp; int myuid=getuid(); int fd; char filepath[128]; char buf[256]; char *ptr; int nbytes; char procname[64]; int cnt=0; char *pTargetProg; if ((dp = opendir(path)) == NULL) { return -1; } pTargetProg = (char *)malloc(strlen(progName) + 1); if (pTargetProg == NULL) { logError("file: "__FILE__", line: %d, " \ "malloc %d bytes fail", __LINE__, \ (int)strlen(progName) + 1); return -1; } ptr = strrchr(progName, '/'); if (ptr == NULL) { strcpy(pTargetProg, progName); } else { strcpy(pTargetProg, ptr + 1); } while( (dirp = readdir(dp)) != NULL ) { if (strcmp(dirp->d_name, ".")==0 || strcmp(dirp->d_name, "..")==0 ) { continue; } sprintf(fullpath, "%s/%s", path, dirp->d_name); memset(&statbuf, 0, sizeof(statbuf)); if (lstat(fullpath, &statbuf)<0) { continue; } if ((bAllOwners || (statbuf.st_uid == myuid)) && S_ISDIR(statbuf.st_mode)) { sprintf(filepath, "%s/cmdline", fullpath); if ((fd = open(filepath, O_RDONLY))<0) { continue; } memset(buf, 0, 256); if ((nbytes = read(fd, buf, 255)) < 0){ close(fd); continue; } close(fd); if (*buf == '\0') { continue; } ptr = strrchr(buf, '/'); if (ptr == NULL) { snprintf(procname, 64, "%s", buf); } else { snprintf(procname, 64, "%s", ptr + 1); } if (strcmp(procname, pTargetProg) == 0) { if (pids != NULL) { if (cnt >= arrSize) { break; } pids[cnt] = atoi(dirp->d_name); } cnt++; } } } free(pTargetProg); closedir(dp); return cnt; } int getExecResult(const char *command, char *output, const int buff_size) { FILE *fp; char *pCurrent; int bytes_read; int remain_bytes; if((fp=popen(command, "r")) == NULL) { return errno != 0 ? errno : EMFILE; } pCurrent = output; remain_bytes = buff_size; while (remain_bytes > 0 && \ (bytes_read=fread(pCurrent, 1, remain_bytes, fp)) > 0) { pCurrent += bytes_read; remain_bytes -= bytes_read; } pclose(fp); if (remain_bytes <= 0) { return ENOSPC; } *pCurrent = '\0'; return 0; } #endif char *toLowercase(char *src) { char *p; p = src; while (*p != '\0') { if (*p >= 'A' && *p <= 'Z') { *p += 32; } p++; } return src; } char *toUppercase(char *src) { char *p; p = src; while (*p != '\0') { if (*p >= 'a' && *p <= 'z') { *p -= 32; } p++; } return src; } void daemon_init(bool bCloseFiles) { #ifndef WIN32 pid_t pid; int i; if((pid=fork()) != 0) { exit(0); } setsid(); if((pid=fork()) != 0) { exit(0); } #ifdef DEBUG_FLAG #define MAX_CORE_FILE_SIZE (256 * 1024 * 1024) if (set_rlimit(RLIMIT_CORE, MAX_CORE_FILE_SIZE) != 0) { logWarning("file: "__FILE__", line: %d, " \ "set max core dump file size to %d MB fail, " \ "errno: %d, error info: %s", \ __LINE__, MAX_CORE_FILE_SIZE / (1024 * 1024), \ errno, STRERROR(errno)); } #else if (chdir("/") != 0) { logWarning("file: "__FILE__", line: %d, " \ "change directory to / fail, " \ "errno: %d, error info: %s", \ __LINE__, errno, STRERROR(errno)); } #endif if (bCloseFiles) { for(i=0; i<=2; i++) { close(i); } } #endif return; } char *bin2hex(const char *s, const int len, char *szHexBuff) { unsigned char *p; unsigned char *pEnd; int nLen; nLen = 0; pEnd = (unsigned char *)s + len; for (p=(unsigned char *)s; p=pStr; p--) { if (!(' ' == *p || '\n' == *p || '\r' == *p || '\t' == *p)) { break; } } if (p != pEnd) { *(p+1) = '\0'; } return pStr; } char *trim(char *pStr) { trim_right(pStr); trim_left(pStr); return pStr; } char *formatDateYYYYMMDDHHMISS(const time_t t, char *szDateBuff, const int nSize) { time_t timer = t; struct tm tm; localtime_r(&timer, &tm); snprintf(szDateBuff, nSize, "%04d%02d%02d%02d%02d%02d", \ tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, \ tm.tm_hour, tm.tm_min, tm.tm_sec); return szDateBuff; } int getOccurCount(const char *src, const char seperator) { int count; char *p; count = 0; p = strchr(src, seperator); while (p != NULL) { count++; p = strchr(p + 1, seperator); } return count; } char **split(char *src, const char seperator, const int nMaxCols, int *nColCount) { char **pCols; char **pCurrent; char *p; int i; int nLastIndex; if (src == NULL) { *nColCount = 0; return NULL; } *nColCount = 1; p = strchr(src, seperator); while (p != NULL) { (*nColCount)++; p = strchr(p + 1, seperator); } if (nMaxCols > 0 && (*nColCount) > nMaxCols) { *nColCount = nMaxCols; } pCurrent = pCols = (char **)malloc(sizeof(char *) * (*nColCount)); if (pCols == NULL) { logError("file: "__FILE__", line: %d, " \ "malloc %d bytes fail", __LINE__, \ (int)sizeof(char *) * (*nColCount)); return NULL; } p = src; nLastIndex = *nColCount - 1; for (i=0; i<*nColCount; i++) { *pCurrent = p; pCurrent++; p = strchr(p, seperator); if (i != nLastIndex) { *p = '\0'; p++; } } return pCols; } void freeSplit(char **p) { if (p != NULL) { free(p); } } int splitEx(char *src, const char seperator, char **pCols, const int nMaxCols) { char *p; char **pCurrent; int count = 0; if (nMaxCols <= 0) { return 0; } p = src; pCurrent = pCols; while (true) { *pCurrent = p; pCurrent++; count++; if (count >= nMaxCols) { break; } p = strchr(p, seperator); if (p == NULL) { break; } *p = '\0'; p++; } return count; } int my_strtok(char *src, const char *delim, char **pCols, const int nMaxCols) { char *p; char **pCurrent; int count; bool bWordEnd; if (src == NULL || pCols == NULL) { return -1; } if (nMaxCols <= 0) { return 0; } p = src; pCurrent = pCols; while (*p != '\0') { if (strchr(delim, *p) == NULL) { break; } p++; } if (*p == '\0') { return 0; } *pCurrent = p; bWordEnd = false; count = 1; if (count >= nMaxCols) { return count; } while (*p != '\0') { if (strchr(delim, *p) != NULL) { *p = '\0'; bWordEnd = true; } else { if (bWordEnd) { pCurrent++; *pCurrent = p; count++; if (count >= nMaxCols) { break; } bWordEnd = false; } } p++; } return count; } int str_replace(const char *s, const int src_len, const char *replaced, const char *new_str, char *dest, const int dest_size) { const char *pStart; const char *pEnd; char *pDest; const char *p; int old_len; int new_len; int len; int max_dest_len; int remain_len; if (dest_size <= 0) { return 0; } max_dest_len = dest_size - 1; old_len = strlen(replaced); new_len = strlen(new_str); if (old_len == 0) { len = src_len < max_dest_len ? src_len : max_dest_len; memcpy(dest, s, len); dest[len] = '\0'; return len; } remain_len = max_dest_len; pDest = dest; pStart = s; pEnd = s + src_len; while (1) { p = strstr(pStart, replaced); if (p == NULL) { break; } len = p - pStart; if (len > 0) { if (len < remain_len) { memcpy(pDest, pStart, len); pDest += len; remain_len -= len; } else { memcpy(pDest, pStart, remain_len); pDest += remain_len; *pDest = '\0'; return pDest - dest; } } if (new_len < remain_len) { memcpy(pDest, new_str, new_len); pDest += new_len; remain_len -= new_len; } else { memcpy(pDest, new_str, remain_len); pDest += remain_len; *pDest = '\0'; return pDest - dest; } pStart = p + old_len; } len = pEnd - pStart; if (len > 0) { if (len > remain_len) { len = remain_len; } memcpy(pDest, pStart, len); pDest += len; } *pDest = '\0'; return pDest - dest; } bool fileExists(const char *filename) { return access(filename, 0) == 0; } bool isDir(const char *filename) { struct stat buf; if (stat(filename, &buf) != 0) { return false; } return S_ISDIR(buf.st_mode); } bool isFile(const char *filename) { struct stat buf; if (stat(filename, &buf) != 0) { return false; } return S_ISREG(buf.st_mode); } void chopPath(char *filePath) { int lastIndex; if (*filePath == '\0') { return; } lastIndex = strlen(filePath) - 1; if (filePath[lastIndex] == '/') { filePath[lastIndex] = '\0'; } } int getFileContent(const char *filename, char **buff, int64_t *file_size) { int fd; fd = open(filename, O_RDONLY); if (fd < 0) { *buff = NULL; *file_size = 0; logError("file: "__FILE__", line: %d, " \ "open file %s fail, " \ "errno: %d, error info: %s", __LINE__, \ filename, errno, STRERROR(errno)); return errno != 0 ? errno : ENOENT; } if ((*file_size=lseek(fd, 0, SEEK_END)) < 0) { *buff = NULL; *file_size = 0; close(fd); logError("file: "__FILE__", line: %d, " \ "lseek file %s fail, " \ "errno: %d, error info: %s", __LINE__, \ filename, errno, STRERROR(errno)); return errno != 0 ? errno : EIO; } *buff = (char *)malloc(*file_size + 1); if (*buff == NULL) { *file_size = 0; close(fd); logError("file: "__FILE__", line: %d, " \ "malloc %d bytes fail", __LINE__, \ (int)(*file_size + 1)); return errno != 0 ? errno : ENOMEM; } if (lseek(fd, 0, SEEK_SET) < 0) { *buff = NULL; *file_size = 0; close(fd); logError("file: "__FILE__", line: %d, " \ "lseek file %s fail, " \ "errno: %d, error info: %s", __LINE__, \ filename, errno, STRERROR(errno)); return errno != 0 ? errno : EIO; } if (read(fd, *buff, *file_size) != *file_size) { free(*buff); *buff = NULL; *file_size = 0; close(fd); logError("file: "__FILE__", line: %d, " \ "read from file %s fail, " \ "errno: %d, error info: %s", __LINE__, \ filename, errno, STRERROR(errno)); return errno != 0 ? errno : EIO; } (*buff)[*file_size] = '\0'; close(fd); return 0; } int getFileContentEx(const char *filename, char *buff, \ int64_t offset, int64_t *size) { int fd; int read_bytes; if (*size <= 0) { logError("file: "__FILE__", line: %d, " \ "invalid size: %"PRId64, \ __LINE__, *size); return EINVAL; } fd = open(filename, O_RDONLY); if (fd < 0) { *size = 0; logError("file: "__FILE__", line: %d, " \ "open file %s fail, " \ "errno: %d, error info: %s", __LINE__, \ filename, errno, STRERROR(errno)); return errno != 0 ? errno : ENOENT; } if (offset > 0 && lseek(fd, offset, SEEK_SET) < 0) { *size = 0; close(fd); logError("file: "__FILE__", line: %d, " \ "lseek file %s fail, " \ "errno: %d, error info: %s", __LINE__, \ filename, errno, STRERROR(errno)); return errno != 0 ? errno : EIO; } if ((read_bytes=read(fd, buff, *size)) < 0) { *size = 0; close(fd); logError("file: "__FILE__", line: %d, " \ "read from file %s fail, " \ "errno: %d, error info: %s", __LINE__, \ filename, errno, STRERROR(errno)); return errno != 0 ? errno : EIO; } *size = read_bytes; *(buff + (*size)) = '\0'; close(fd); return 0; } int writeToFile(const char *filename, const char *buff, const int file_size) { int fd; int result; fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644); if (fd < 0) { result = errno != 0 ? errno : EIO; logError("file: "__FILE__", line: %d, " \ "open file %s fail, " \ "errno: %d, error info: %s", \ __LINE__, filename, \ result, STRERROR(result)); return result; } if (write(fd, buff, file_size) != file_size) { result = errno != 0 ? errno : EIO; logError("file: "__FILE__", line: %d, " \ "write file %s fail, " \ "errno: %d, error info: %s", \ __LINE__, filename, \ result, STRERROR(result)); close(fd); return result; } if (fsync(fd) != 0) { result = errno != 0 ? errno : EIO; logError("file: "__FILE__", line: %d, " \ "fsync file \"%s\" fail, " \ "errno: %d, error info: %s", \ __LINE__, filename, \ result, STRERROR(result)); close(fd); return result; } close(fd); return 0; } int safeWriteToFile(const char *filename, const char *buff, \ const int file_size) { char tmpFilename[MAX_PATH_SIZE]; int result; snprintf(tmpFilename, sizeof(tmpFilename), "%s.tmp", filename); if ((result=writeToFile(tmpFilename, buff, file_size)) != 0) { return result; } if (rename(tmpFilename, filename) != 0) { result = errno != 0 ? errno : EIO; logError("file: "__FILE__", line: %d, " \ "rename file \"%s\" to \"%s\" fail, " \ "errno: %d, error info: %s", \ __LINE__, tmpFilename, filename, \ result, STRERROR(result)); return result; } return 0; } void short2buff(const short n, char *buff) { unsigned char *p; p = (unsigned char *)buff; *p++ = (n >> 8) & 0xFF; *p++ = n & 0xFF; } short buff2short(const char *buff) { return (short)((((unsigned char)(*(buff))) << 8) | \ ((unsigned char)(*(buff+1)))); } void int2buff(const int n, char *buff) { unsigned char *p; p = (unsigned char *)buff; *p++ = (n >> 24) & 0xFF; *p++ = (n >> 16) & 0xFF; *p++ = (n >> 8) & 0xFF; *p++ = n & 0xFF; } int buff2int(const char *buff) { return (((unsigned char)(*buff)) << 24) | \ (((unsigned char)(*(buff+1))) << 16) | \ (((unsigned char)(*(buff+2))) << 8) | \ ((unsigned char)(*(buff+3))); } void long2buff(int64_t n, char *buff) { unsigned char *p; p = (unsigned char *)buff; *p++ = (n >> 56) & 0xFF; *p++ = (n >> 48) & 0xFF; *p++ = (n >> 40) & 0xFF; *p++ = (n >> 32) & 0xFF; *p++ = (n >> 24) & 0xFF; *p++ = (n >> 16) & 0xFF; *p++ = (n >> 8) & 0xFF; *p++ = n & 0xFF; } int64_t buff2long(const char *buff) { unsigned char *p; p = (unsigned char *)buff; return (((int64_t)(*p)) << 56) | \ (((int64_t)(*(p+1))) << 48) | \ (((int64_t)(*(p+2))) << 40) | \ (((int64_t)(*(p+3))) << 32) | \ (((int64_t)(*(p+4))) << 24) | \ (((int64_t)(*(p+5))) << 16) | \ (((int64_t)(*(p+6))) << 8) | \ ((int64_t)(*(p+7))); } int fd_gets(int fd, char *buff, const int size, int once_bytes) { char *pDest; char *p; char *pEnd; int read_bytes; int remain_bytes; int rewind_bytes; if (once_bytes <= 0) { once_bytes = 1; } pDest = buff; remain_bytes = size - 1; while (remain_bytes > 0) { if (once_bytes > remain_bytes) { once_bytes = remain_bytes; } read_bytes = read(fd, pDest, once_bytes); if (read_bytes < 0) { return -1; } if (read_bytes == 0) { break; } pEnd = pDest + read_bytes; for (p=pDest; p= value)) { return 0; } limit.rlim_cur = value; if (setrlimit(resource, &limit) != 0) { logError("file: "__FILE__", line: %d, " \ "call setrlimit fail, resource=%d, value=%d, " \ "errno: %d, error info: %s", \ __LINE__, resource, (int)value, \ errno, STRERROR(errno)); return errno != 0 ? errno : EPERM; } return 0; } bool is_filename_secure(const char *filename, const int len) { if (len < 3) { return true; } if (memcmp(filename, "../", 3) == 0) { return false; } return (strstr(filename, "/../") == NULL); } void load_log_level(IniContext *pIniContext) { set_log_level(iniGetStrValue(NULL, "log_level", pIniContext)); } int load_log_level_ex(const char *conf_filename) { int result; IniContext iniContext; if ((result=iniLoadFromFile(conf_filename, &iniContext)) != 0) { logError("file: "__FILE__", line: %d, " \ "load conf file \"%s\" fail, ret code: %d", \ __LINE__, conf_filename, result); return result; } load_log_level(&iniContext); iniFreeContext(&iniContext); return 0; } void set_log_level(char *pLogLevel) { if (pLogLevel != NULL) { toUppercase(pLogLevel); if ( strncmp(pLogLevel, "DEBUG", 5) == 0 || \ strcmp(pLogLevel, "LOG_DEBUG") == 0) { g_log_context.log_level = LOG_DEBUG; } else if ( strncmp(pLogLevel, "INFO", 4) == 0 || \ strcmp(pLogLevel, "LOG_INFO") == 0) { g_log_context.log_level = LOG_INFO; } else if ( strncmp(pLogLevel, "NOTICE", 6) == 0 || \ strcmp(pLogLevel, "LOG_NOTICE") == 0) { g_log_context.log_level = LOG_NOTICE; } else if ( strncmp(pLogLevel, "WARN", 4) == 0 || \ strcmp(pLogLevel, "LOG_WARNING") == 0) { g_log_context.log_level = LOG_WARNING; } else if ( strncmp(pLogLevel, "ERR", 3) == 0 || \ strcmp(pLogLevel, "LOG_ERR") == 0) { g_log_context.log_level = LOG_ERR; } else if ( strncmp(pLogLevel, "CRIT", 4) == 0 || \ strcmp(pLogLevel, "LOG_CRIT") == 0) { g_log_context.log_level = LOG_CRIT; } else if ( strncmp(pLogLevel, "ALERT", 5) == 0 || \ strcmp(pLogLevel, "LOG_ALERT") == 0) { g_log_context.log_level = LOG_ALERT; } else if ( strncmp(pLogLevel, "EMERG", 5) == 0 || \ strcmp(pLogLevel, "LOG_EMERG") == 0) { g_log_context.log_level = LOG_EMERG; } } } int fd_add_flags(int fd, int adding_flags) { int flags; flags = fcntl(fd, F_GETFL, 0); if (flags < 0) { logError("file: "__FILE__", line: %d, " \ "fcntl fail, errno: %d, error info: %s.", \ __LINE__, errno, STRERROR(errno)); return errno != 0 ? errno : EACCES; } if (fcntl(fd, F_SETFL, flags | adding_flags) == -1) { logError("file: "__FILE__", line: %d, " \ "fcntl fail, errno: %d, error info: %s.", \ __LINE__, errno, STRERROR(errno)); return errno != 0 ? errno : EACCES; } return 0; } int set_run_by(const char *group_name, const char *username) { #ifndef WIN32 struct group *pGroup; struct passwd *pUser; int nErrNo; if (group_name != NULL && *group_name != '\0') { pGroup = getgrnam(group_name); if (pGroup == NULL) { nErrNo = errno != 0 ? errno : ENOENT; logError("file: "__FILE__", line: %d, " \ "getgrnam %s fail, errno: %d, error info: %s.", \ __LINE__, group_name, nErrNo, STRERROR(nErrNo)); return nErrNo; } if (setegid(pGroup->gr_gid) != 0) { nErrNo = errno != 0 ? errno : EPERM; logError("file: "__FILE__", line: %d, " \ "setegid fail, errno: %d, error info: %s.", \ __LINE__, nErrNo, STRERROR(nErrNo)); return nErrNo; } } if (username != NULL && *username != '\0') { pUser = getpwnam(username); if (pUser == NULL) { nErrNo = errno != 0 ? errno : ENOENT; logError("file: "__FILE__", line: %d, " \ "getpwnam %s fail, errno: %d, error info: %s.", \ __LINE__, username, nErrNo, STRERROR(nErrNo)); return nErrNo; } if (seteuid(pUser->pw_uid) != 0) { nErrNo = errno != 0 ? errno : EPERM; logError("file: "__FILE__", line: %d, " \ "seteuid fail, errno: %d, error info: %s.", \ __LINE__, nErrNo, STRERROR(nErrNo)); return nErrNo; } } #endif return 0; } int load_allow_hosts(IniContext *pIniContext, \ in_addr_t **allow_ip_addrs, int *allow_ip_count) { int count; IniItem *pItem; IniItem *pItemStart; IniItem *pItemEnd; char *pItemValue; char *pStart; char *pEnd; char *p; char *pTail; int alloc_count; int nHeadLen; int i; in_addr_t addr; char hostname[256]; if ((pItemStart=iniGetValuesEx(NULL, "allow_hosts", \ pIniContext, &count)) == NULL) { *allow_ip_count = -1; /* -1 means match any ip address */ *allow_ip_addrs = NULL; return 0; } pItemEnd = pItemStart + count; for (pItem=pItemStart; pItemvalue, "*") == 0) { *allow_ip_count = -1; /* -1 means match any ip address*/ *allow_ip_addrs = NULL; return 0; } } alloc_count = count; *allow_ip_count = 0; *allow_ip_addrs = (in_addr_t *)malloc(sizeof(in_addr_t) * alloc_count); if (*allow_ip_addrs == NULL) { logError("file: "__FILE__", line: %d, " \ "malloc %d bytes fail, errno: %d, error info: %s.", \ __LINE__, (int)sizeof(in_addr_t) * alloc_count, \ errno, STRERROR(errno)); return errno != 0 ? errno : ENOMEM; } for (pItem=pItemStart; pItemvalue) == '\0') { continue; } pStart = strchr(pItem->value, '['); if (pStart == NULL) { addr = getIpaddrByName(pItem->value, NULL, 0); if (addr == INADDR_NONE) { logWarning("file: "__FILE__", line: %d, " \ "invalid host name: %s", \ __LINE__, pItem->value); } else { if (alloc_count < (*allow_ip_count) + 1) { alloc_count = (*allow_ip_count) + \ (pItemEnd - pItem); *allow_ip_addrs = (in_addr_t *)realloc( *allow_ip_addrs, sizeof(in_addr_t)*alloc_count); if (*allow_ip_addrs == NULL) { logError("file: "__FILE__", line: %d, "\ "malloc %d bytes fail, " \ "errno: %d, error info: %s", \ __LINE__, (int)sizeof(in_addr_t) * alloc_count, \ errno, STRERROR(errno)); return errno != 0 ? errno : ENOMEM; } } (*allow_ip_addrs)[*allow_ip_count] = addr; (*allow_ip_count)++; } continue; } pEnd = strchr(pStart, ']'); if (pEnd == NULL) { logWarning("file: "__FILE__", line: %d, " \ "invalid host name: %s, expect \"]\"", \ __LINE__, pItem->value); continue; } pItemValue = strdup(pItem->value); if (pItemValue == NULL) { logWarning("file: "__FILE__", line: %d, " \ "strdup fail, " \ "errno: %d, error info: %s.", \ __LINE__, errno, STRERROR(errno)); continue; } nHeadLen = pStart - pItem->value; pStart = pItemValue + nHeadLen; pEnd = pItemValue + (pEnd - pItem->value); pTail = pEnd + 1; memcpy(hostname, pItem->value, nHeadLen); p = pStart + 1; //skip [ while (p <= pEnd) { char *pNumStart1; char *pNumStart2; int nStart; int nEnd; int nNumLen1; int nNumLen2; char end_ch1; char end_ch2; char szFormat[16]; while (*p == ' ' || *p == '\t') //trim prior spaces { p++; } pNumStart1 = p; while (*p >='0' && *p <= '9') { p++; } nNumLen1 = p - pNumStart1; while (*p == ' ' || *p == '\t') //trim tail spaces { p++; } if (!(*p == ',' || *p == '-' || *p == ']')) { logWarning("file: "__FILE__", line: %d, " \ "invalid char \"%c\" in host name: %s",\ __LINE__, *p, pItem->value); break; } end_ch1 = *p; *(pNumStart1 + nNumLen1) = '\0'; if (nNumLen1 == 0) { logWarning("file: "__FILE__", line: %d, " \ "invalid host name: %s, " \ "empty entry before \"%c\"", \ __LINE__, pItem->value, end_ch1); break; } nStart = atoi(pNumStart1); if (end_ch1 == '-') { p++; //skip - /* trim prior spaces */ while (*p == ' ' || *p == '\t') { p++; } pNumStart2 = p; while (*p >='0' && *p <= '9') { p++; } nNumLen2 = p - pNumStart2; /* trim tail spaces */ while (*p == ' ' || *p == '\t') { p++; } if (!(*p == ',' || *p == ']')) { logWarning("file: "__FILE__", line: %d, " \ "invalid char \"%c\" in host name: %s",\ __LINE__, *p, pItem->value); break; } end_ch2 = *p; *(pNumStart2 + nNumLen2) = '\0'; if (nNumLen2 == 0) { logWarning("file: "__FILE__", line: %d, " \ "invalid host name: %s, " \ "empty entry before \"%c\"", \ __LINE__, pItem->value, end_ch2); break; } nEnd = atoi(pNumStart2); } else { nEnd = nStart; } if (alloc_count < *allow_ip_count+(nEnd - nStart + 1)) { alloc_count = *allow_ip_count + (nEnd - nStart) + (pItemEnd - pItem); *allow_ip_addrs = (in_addr_t *)realloc( *allow_ip_addrs, sizeof(in_addr_t)*alloc_count); if (*allow_ip_addrs == NULL) { logError("file: "__FILE__", line: %d, "\ "malloc %d bytes fail, " \ "errno: %d, error info: %s.", \ __LINE__, \ (int)sizeof(in_addr_t) * \ alloc_count,\ errno, STRERROR(errno)); free(pItemValue); return errno != 0 ? errno : ENOMEM; } } sprintf(szFormat, "%%0%dd%%s", nNumLen1); for (i=nStart; i<=nEnd; i++) { sprintf(hostname + nHeadLen, szFormat, \ i, pTail); addr = getIpaddrByName(hostname, NULL, 0); if (addr == INADDR_NONE) { logWarning("file: "__FILE__", line: %d, " \ "invalid host name: %s", \ __LINE__, hostname); } else { (*allow_ip_addrs)[*allow_ip_count]=addr; (*allow_ip_count)++; } } p++; } free(pItemValue); } if (*allow_ip_count == 0) { logWarning("file: "__FILE__", line: %d, " \ "allow ip count: 0", __LINE__); } if (*allow_ip_count > 0) { qsort(*allow_ip_addrs, *allow_ip_count, sizeof(in_addr_t), \ cmp_by_ip_addr_t); } /* printf("*allow_ip_count=%d\n", *allow_ip_count); for (i=0; i<*allow_ip_count; i++) { struct in_addr address; address.s_addr = (*allow_ip_addrs)[i]; printf("%s\n", inet_ntoa(address)); } */ return 0; } int cmp_by_ip_addr_t(const void *p1, const void *p2) { return memcmp((in_addr_t *)p1, (in_addr_t *)p2, sizeof(in_addr_t)); } int parse_bytes(char *pStr, const int default_unit_bytes, int64_t *bytes) { char *pReservedEnd; pReservedEnd = NULL; *bytes = strtol(pStr, &pReservedEnd, 10); if (*bytes < 0) { logError("file: "__FILE__", line: %d, " \ "bytes: %"PRId64" < 0", __LINE__, *bytes); return EINVAL; } if (pReservedEnd == NULL || *pReservedEnd == '\0') { *bytes *= default_unit_bytes; } else if (*pReservedEnd == 'G' || *pReservedEnd == 'g') { *bytes *= 1024 * 1024 * 1024; } else if (*pReservedEnd == 'M' || *pReservedEnd == 'm') { *bytes *= 1024 * 1024; } else if (*pReservedEnd == 'K' || *pReservedEnd == 'k') { *bytes *= 1024; } return 0; } int set_rand_seed() { struct timeval tv; if (gettimeofday(&tv, NULL) != 0) { logError("file: "__FILE__", line: %d, " \ "call gettimeofday fail, " \ "errno=%d, error info: %s", \ __LINE__, errno, STRERROR(errno)); return errno != 0 ? errno : EPERM; } srand(tv.tv_sec ^ tv.tv_usec); return 0; } int get_time_item_from_conf(IniContext *pIniContext, \ const char *item_name, TimeInfo *pTimeInfo, \ const byte default_hour, const byte default_minute) { char *pValue; int hour; int minute; pValue = iniGetStrValue(NULL, item_name, pIniContext); if (pValue == NULL) { pTimeInfo->hour = default_hour; pTimeInfo->minute = default_minute; return 0; } if (sscanf(pValue, "%d:%d", &hour, &minute) != 2) { logError("file: "__FILE__", line: %d, " \ "item \"%s\" 's value \"%s\" is not an valid time", \ __LINE__, item_name, pValue); return EINVAL; } if ((hour < 0 || hour > 23) || (minute < 0 || minute > 59)) { logError("file: "__FILE__", line: %d, " \ "item \"%s\" 's value \"%s\" is not an valid time", \ __LINE__, item_name, pValue); return EINVAL; } pTimeInfo->hour = (byte)hour; pTimeInfo->minute = (byte)minute; return 0; } char *urlencode(const char *src, const int src_len, char *dest, int *dest_len) { static unsigned char hex_chars[] = "0123456789ABCDEF"; const unsigned char *pSrc; const unsigned char *pEnd; char *pDest; pDest = dest; pEnd = (unsigned char *)src + src_len; for (pSrc=(unsigned char *)src; pSrc= '0' && *pSrc <= '9') || (*pSrc >= 'a' && *pSrc <= 'z') || (*pSrc >= 'A' && *pSrc <= 'Z') || (*pSrc == '_' || *pSrc == '-' || *pSrc == '.')) { *pDest++ = *pSrc; } else if (*pSrc == ' ') { *pDest++ = '+'; } else { *pDest++ = '%'; *pDest++ = hex_chars[(*pSrc) >> 4]; *pDest++ = hex_chars[(*pSrc) & 0x0F]; } } *pDest = '\0'; *dest_len = pDest - dest; return dest; } char *urldecode(const char *src, const int src_len, char *dest, int *dest_len) { (void)urldecode_ex(src, src_len, dest, dest_len); *(dest + *dest_len) = '\0'; return dest; } char *urldecode_ex(const char *src, const int src_len, char *dest, int *dest_len) { #define IS_HEX_CHAR(ch) \ ((ch >= '0' && ch <= '9') || \ (ch >= 'a' && ch <= 'f') || \ (ch >= 'A' && ch <= 'F')) #define HEX_VALUE(ch, value) \ if (ch >= '0' && ch <= '9') \ { \ value = ch - '0'; \ } \ else if (ch >= 'a' && ch <= 'f') \ { \ value = ch - 'a' + 10; \ } \ else \ { \ value = ch - 'A' + 10; \ } const unsigned char *pSrc; const unsigned char *pEnd; char *pDest; unsigned char cHigh; unsigned char cLow; int valHigh; int valLow; pDest = dest; pSrc = (unsigned char *)src; pEnd = (unsigned char *)src + src_len; while (pSrc < pEnd) { if (*pSrc == '%' && pSrc + 2 < pEnd) { cHigh = *(pSrc + 1); cLow = *(pSrc + 2); if (IS_HEX_CHAR(cHigh) && IS_HEX_CHAR(cLow)) { HEX_VALUE(cHigh, valHigh) HEX_VALUE(cLow, valLow) *pDest++ = (valHigh << 4) | valLow; pSrc += 3; } else { *pDest++ = *pSrc; pSrc++; } } else if (*pSrc == '+') { *pDest++ = ' '; pSrc++; } else { *pDest++ = *pSrc; pSrc++; } } *dest_len = pDest - dest; return dest; } int buffer_strcpy(BufferInfo *pBuff, const char *str) { pBuff->length = strlen(str); if (pBuff->alloc_size <= pBuff->length) { if (pBuff->buff != NULL) { free(pBuff->buff); } pBuff->alloc_size = pBuff->length + 1; pBuff->buff = (char *)malloc(pBuff->alloc_size); if (pBuff->buff == NULL) { logError("file: "__FILE__", line: %d, " \ "malloc %d bytes fail, " \ "errno: %d, error info: %s", \ __LINE__, pBuff->alloc_size, \ errno, STRERROR(errno)); pBuff->alloc_size = 0; return errno != 0 ? errno : ENOMEM; } } memcpy(pBuff->buff, str, pBuff->length + 1); return 0; } int buffer_memcpy(BufferInfo *pBuff, const char *buff, const int len) { pBuff->length = len; if (pBuff->alloc_size <= pBuff->length) { if (pBuff->buff != NULL) { free(pBuff->buff); } pBuff->alloc_size = pBuff->length; pBuff->buff = (char *)malloc(pBuff->alloc_size); if (pBuff->buff == NULL) { logError("file: "__FILE__", line: %d, " \ "malloc %d bytes fail, " \ "errno: %d, error info: %s", \ __LINE__, pBuff->alloc_size, \ errno, STRERROR(errno)); pBuff->alloc_size = 0; return errno != 0 ? errno : ENOMEM; } } memcpy(pBuff->buff, buff, pBuff->length); return 0; } int set_timer(const int first_remain_seconds, const int interval, \ void (*sighandler)(int)) { struct itimerval value; struct sigaction act; memset(&act, 0, sizeof(act)); sigemptyset(&act.sa_mask); act.sa_handler = sighandler; if(sigaction(SIGALRM, &act, NULL) < 0) { logError("file: "__FILE__", line: %d, " \ "call sigaction fail, errno: %d, error info: %s", \ __LINE__, errno, STRERROR(errno)); return errno != 0 ? errno : EINVAL; } memset(&value, 0, sizeof(value)); value.it_interval.tv_sec = interval; value.it_value.tv_sec = first_remain_seconds; if (setitimer(ITIMER_REAL, &value, NULL) < 0) { logError("file: "__FILE__", line: %d, " \ "call setitimer fail, errno: %d, error info: %s", \ __LINE__, errno, STRERROR(errno)); return errno != 0 ? errno : EINVAL; } return 0; } int set_file_utimes(const char *filename, const time_t new_time) { struct timeval tvs[2]; tvs[0].tv_sec = new_time; tvs[0].tv_usec = 0; tvs[1].tv_sec = new_time; tvs[1].tv_usec = 0; if (utimes(filename, tvs) != 0) { logWarning("file: "__FILE__", line: %d, " \ "call utimes file: %s fail" \ ", errno: %d, error info: %s", \ __LINE__, filename, errno, STRERROR(errno)); return errno != 0 ? errno : ENOENT; } return 0; } int ignore_signal_pipe() { struct sigaction act; memset(&act, 0, sizeof(act)); sigemptyset(&act.sa_mask); act.sa_handler = SIG_IGN; if(sigaction(SIGPIPE, &act, NULL) < 0) { logError("file: "__FILE__", line: %d, " \ "call sigaction fail, errno: %d, error info: %s", \ __LINE__, errno, STRERROR(errno)); return errno; } return 0; }