From 3040f3a5f35a712c2766c020ad0141d598b69e21 Mon Sep 17 00:00:00 2001
From: kuailexs <952415538@qq.com>
Date: Fri, 15 Oct 2021 11:49:57 +0800
Subject: [PATCH] klogd

---
 klogd/Android.mk |  24 ++++++
 klogd/klogd.c    | 185 +++++++++++++++++++++++++++++++++++++++++++++++
 rootdir/init.rc  |   7 ++
 3 files changed, 216 insertions(+)
 create mode 100644 klogd/Android.mk
 create mode 100644 klogd/klogd.c

diff --git a/klogd/Android.mk b/klogd/Android.mk
new file mode 100644
index 0000000..9074501
--- /dev/null
+++ b/klogd/Android.mk
@@ -0,0 +1,24 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+
+
+
+LOCAL_SRC_FILES := \
+	klogd.c
+
+LOCAL_C_INCLUDES := bionic/libc/bionic
+
+LOCAL_STATIC_LIBRARIES := \
+	libc \
+
+LOCAL_MODULE := klogd
+
+LOCAL_FORCE_STATIC_EXECUTABLE := true
+
+LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)/sbin
+
+# Including this will define $(intermediates).
+#
+include $(BUILD_EXECUTABLE)
+
diff --git a/klogd/klogd.c b/klogd/klogd.c
new file mode 100644
index 0000000..8402d27
--- /dev/null
+++ b/klogd/klogd.c
@@ -0,0 +1,185 @@
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/klog.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#define FALLBACK_KLOG_BUF_SHIFT	17	/* CONFIG_LOG_BUF_SHIFT from our kernel */
+#define FALLBACK_KLOG_BUF_LEN	(1 << FALLBACK_KLOG_BUF_SHIFT)
+
+// data 分区是否挂载 1 是 0 否
+int is_mount_data() {
+    int mount_stat = 0;
+    char s[2000];
+    FILE *f = fopen("/proc/mounts", "r");
+
+    while (fgets(s, 2000, f)) {
+        char *c, *e = s;
+
+        for (c = s; *c; c++) {
+            if (*c == ' ') {
+                e = c + 1;
+                break;
+            }
+        }
+
+        for (c = e; *c; c++) {
+            if (*c == ' ') {
+                *c = '\0';
+                break;
+            }
+        }
+
+        if(strcmp(e,"/data")){
+            mount_stat = 1;
+            break;
+        }
+    }
+
+    fclose(f);
+
+    //etc  目录检查
+    struct stat filestat;
+    if( stat("/etc",&filestat) != 0 ){
+        fprintf(stderr,"%s is not found ! \n","/etc");
+        mount_stat = 0;
+    }
+    if( S_ISDIR(filestat.st_mode) || S_ISLNK(filestat.st_mode) ){
+        fprintf(stderr,"%s is dir \n","/etc");
+        mount_stat = 1;
+    }else{
+        fprintf(stderr,"%s is not dir\n","/etc");
+        mount_stat = 0;
+    }
+
+    return mount_stat;
+}
+
+struct cache{
+    char *p;
+    struct cache *next;
+};
+struct cache *head = NULL;
+struct cache *end = NULL;
+
+//缓冲区的写到文件中
+void writeFromCache(FILE *fp){
+    fprintf(stderr,"writeFromCache start !\n");
+    while(head != NULL && end != NULL && head != end){
+        fprintf(stderr,"writeFromCache while 1 !\n");
+        fwrite(head->p,strlen(head->p),1,fp);
+        fprintf(stderr,"writeFromCache while 2 !\n");
+        fflush(fp);
+        fprintf(stderr,"writeFromCache while 3 !\n");
+        struct cache *needFree = head;
+        fprintf(stderr,"writeFromCache while 4 !\n");
+        head = head->next;
+        fprintf(stderr,"writeFromCache while 5 !\n");
+        free(needFree->p);
+        free(needFree);
+        fprintf(stderr,"writeFromCache while 6 !\n");
+    }
+}
+//加入缓冲区
+void putCache(const char *p,int n){
+    if(head == NULL){
+       head = (struct cache *)malloc(sizeof(struct cache ));
+       end = head;
+    }
+    end->p = (char *)malloc(n + 1);
+    strcpy(end->p,p);
+    struct cache *next = (struct cache *)malloc(sizeof(struct cache ));;
+    next->p = NULL;
+    next->next = NULL;
+    end->next =  next;
+    end =  next;
+    fprintf(stderr,"putCache end !\n");
+}
+//获取日志文件写入文件
+FILE* get_log_file(){
+    FILE *fp = NULL;
+    fp = fopen("/data/log_kmsg.txt","a");
+    if(fp == NULL){
+        // 文件分区已挂载但无法读取
+        fprintf(stderr,"Eric Open File Failed!!!\n");
+    }else{
+        fprintf(stderr,"Open File ok!!!\n");
+    }
+    return fp;
+}
+//获取内核日志缓冲区大小
+int get_klog_buf_len(){
+    int klog_buf_len = klogctl(KLOG_SIZE_BUFFER, 0, 0);
+
+    if (klog_buf_len <= 0) {
+        klog_buf_len = FALLBACK_KLOG_BUF_LEN;
+        fprintf(stderr,"use default klog_buf_len:%d !!!\n",klog_buf_len);
+    }
+
+    fprintf(stderr,"klog_buf_len:%d !!!\n",klog_buf_len);
+    return klog_buf_len;
+}
+
+int main(int argc, char **argv)
+{
+    char *buffer;
+    char *p;
+    ssize_t ret;
+    int n, op, klog_buf_len;
+
+    int data_mount_stat = is_mount_data();
+    FILE *fp = NULL;
+    if(data_mount_stat){
+        fprintf(stderr,"data mount !\n");
+        fp = get_log_file();
+    }else{
+        fprintf(stderr,"data not mount !\n");
+    }
+
+    klog_buf_len = get_klog_buf_len();
+
+    buffer = (char *)malloc(klog_buf_len + 1);
+
+    if (!buffer) {
+        perror("malloc");
+        return EXIT_FAILURE;
+    }
+
+    p = buffer;
+
+    for(;;){
+        n = klogctl(KLOG_READ_CLEAR, buffer, klog_buf_len);
+        if (n < 0) {
+            fprintf(stderr,"klogctl Failed !\n");
+            continue;
+        }else{
+            fprintf(stderr,"klogctl read count:%d !\n",n);
+        }
+        buffer[n] = '\0';
+        if(data_mount_stat){
+            if(fp == NULL){
+                fp = get_log_file();
+            }
+            fwrite(p,n,1,fp);
+            fflush(fp);
+        }else{
+            data_mount_stat = is_mount_data();
+            if(data_mount_stat){
+                fp = get_log_file();
+                writeFromCache(fp);
+                fwrite(p,n,1,fp);
+                fflush(fp);
+            }else{
+                putCache(p,n);
+            }
+        }
+        sleep(1);
+    }
+    if(data_mount_stat){
+       fclose(fp);
+    }
+    return 0;
+}
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 2843de1..16cfcd1 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -32,6 +32,8 @@ on early-init
 
     start ueventd
 
+    start klogd
+
 on init
     sysclktz 0
 
@@ -653,6 +655,11 @@ service ueventd /sbin/ueventd
     critical
     seclabel u:r:ueventd:s0
 
+service klogd /sbin/klogd
+    class core
+    user root
+    group root
+
 service healthd /sbin/healthd
     class core
     critical
-- 
2.25.1

