128 lines
3.2 KiB
C
128 lines
3.2 KiB
C
#include "nginx.h"
|
|
#include "ip2region/ip2region.h"
|
|
|
|
#define EVENT_SIZE (sizeof(struct inotify_event))
|
|
#define EVENT_BUF_LEN (1024 * (EVENT_SIZE + 16))
|
|
#define INITIAL_BUFFER_SIZE 8192
|
|
|
|
int IP_location(char *string) {
|
|
char *area = NULL;
|
|
char *xdb_path = "ip2region.xdb";
|
|
char *p = strchr(string, ' ');
|
|
char IP[64];
|
|
memset(IP, 0, 64);
|
|
|
|
if ((p - string) > 0) {
|
|
memmove(IP, string, p - string);
|
|
} else {
|
|
printf("Invalid IP string format.\n");
|
|
return -1;
|
|
}
|
|
|
|
if (access(xdb_path, F_OK) == -1) { // 判断 ip2region 地址定位库是否存在
|
|
xdb_path = "ip2region/ip2region.xdb";
|
|
if (access(xdb_path, F_OK) == -1) {
|
|
printf("ip2region.xdb DOESN'T EXIST!\n");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
area = ip2region(xdb_path, IP);
|
|
if (area == NULL) {
|
|
printf("ip2region解析地域错误\n");
|
|
return -1;
|
|
}
|
|
|
|
printf("IP地址:%s, %s\n", IP, area);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void nginx_read_log(const char *filename) {
|
|
int fd = open(filename, O_RDONLY);
|
|
if (fd == -1) {
|
|
perror("open");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
// Move to the end of the file
|
|
if (lseek(fd, 0, SEEK_END) == -1) {
|
|
perror("lseek");
|
|
close(fd);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
int inotify_fd = inotify_init();
|
|
if (inotify_fd < 0) {
|
|
perror("inotify_init");
|
|
close(fd);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
int wd = inotify_add_watch(inotify_fd, filename, IN_MODIFY);
|
|
if (wd == -1) {
|
|
perror("inotify_add_watch");
|
|
close(inotify_fd);
|
|
close(fd);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
char buffer[EVENT_BUF_LEN];
|
|
|
|
// Set the file descriptor to non-blocking mode
|
|
int flags = fcntl(fd, F_GETFL, 0);
|
|
if (flags == -1) {
|
|
perror("fcntl F_GETFL");
|
|
inotify_rm_watch(inotify_fd, wd);
|
|
close(inotify_fd);
|
|
close(fd);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
|
|
perror("fcntl F_SETFL");
|
|
inotify_rm_watch(inotify_fd, wd);
|
|
close(inotify_fd);
|
|
close(fd);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
// Initial dynamic buffer allocation
|
|
size_t buffer_size = INITIAL_BUFFER_SIZE;
|
|
char *read_buf = alloca(buffer_size);
|
|
if (!read_buf) {
|
|
perror("alloca");
|
|
inotify_rm_watch(inotify_fd, wd);
|
|
close(inotify_fd);
|
|
close(fd);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
while (1) {
|
|
int length = read(inotify_fd, buffer, EVENT_BUF_LEN);
|
|
if (length < 0) {
|
|
perror("read");
|
|
break;
|
|
}
|
|
|
|
for (int i = 0; i < length;) {
|
|
struct inotify_event *event = (struct inotify_event *) &buffer[i];
|
|
if (event->mask & IN_MODIFY) {
|
|
int bytes_read;
|
|
while ((bytes_read = read(fd, read_buf, buffer_size - 1)) > 0) {
|
|
read_buf[bytes_read] = '\0';
|
|
IP_location(read_buf);
|
|
}
|
|
if (bytes_read == -1 && errno != EAGAIN) {
|
|
perror("read");
|
|
break;
|
|
}
|
|
}
|
|
i += EVENT_SIZE + event->len;
|
|
}
|
|
}
|
|
|
|
inotify_rm_watch(inotify_fd, wd);
|
|
close(inotify_fd);
|
|
close(fd);
|
|
}
|