/**
* 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 <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <signal.h>
#include <inttypes.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/file.h>
#include <dirent.h>
#include <grp.h>
#include <pwd.h>
#include <math.h>
#include "shared_func.h"
#include "logger.h"
#include "sockopt.h"
#ifdef OS_LINUX
#include <sys/sysinfo.h>
#else
#ifdef OS_FREEBSD
#include <sys/sysctl.h>
#endif
#endif
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", \