0001
0002
0003
0004
0005 #include <errno.h>
0006 #include <limits.h>
0007 #include <signal.h>
0008 #include <stdio.h>
0009 #include <string.h>
0010 #include <unistd.h>
0011 #include <linux/magic.h>
0012 #include <fcntl.h>
0013 #include <sys/vfs.h>
0014
0015 #include "main.h"
0016
0017 #ifndef TRACEFS_MAGIC
0018 # define TRACEFS_MAGIC 0x74726163
0019 #endif
0020
0021 #define _textify(x) #x
0022 #define textify(x) _textify(x)
0023
0024 FILE *trace_pipe_fd;
0025 char *buff;
0026
0027 static int validate_tracefs_mnt(const char *mnt, unsigned long magic)
0028 {
0029 struct statfs st_fs;
0030
0031 if (statfs(mnt, &st_fs) < 0)
0032 return -ENOENT;
0033 if ((unsigned long)st_fs.f_type != magic)
0034 return -ENOENT;
0035
0036 return 0;
0037 }
0038
0039 static bool
0040 find_tracefs_mnt_single(unsigned long magic, char *mnt, const char *mntpt)
0041 {
0042 size_t src_len;
0043
0044 if (validate_tracefs_mnt(mntpt, magic))
0045 return false;
0046
0047 src_len = strlen(mntpt);
0048 if (src_len + 1 >= PATH_MAX) {
0049 p_err("tracefs mount point name too long");
0050 return false;
0051 }
0052
0053 strcpy(mnt, mntpt);
0054 return true;
0055 }
0056
0057 static bool get_tracefs_pipe(char *mnt)
0058 {
0059 static const char * const known_mnts[] = {
0060 "/sys/kernel/debug/tracing",
0061 "/sys/kernel/tracing",
0062 "/tracing",
0063 "/trace",
0064 };
0065 const char *pipe_name = "/trace_pipe";
0066 const char *fstype = "tracefs";
0067 char type[100], format[32];
0068 const char * const *ptr;
0069 bool found = false;
0070 FILE *fp;
0071
0072 for (ptr = known_mnts; ptr < known_mnts + ARRAY_SIZE(known_mnts); ptr++)
0073 if (find_tracefs_mnt_single(TRACEFS_MAGIC, mnt, *ptr))
0074 goto exit_found;
0075
0076 fp = fopen("/proc/mounts", "r");
0077 if (!fp)
0078 return false;
0079
0080
0081 snprintf(format, sizeof(format), "%%*s %%%zds %%99s %%*s %%*d %%*d\\n",
0082 PATH_MAX - strlen(pipe_name) - 1);
0083 while (fscanf(fp, format, mnt, type) == 2)
0084 if (strcmp(type, fstype) == 0) {
0085 found = true;
0086 break;
0087 }
0088 fclose(fp);
0089
0090
0091 if (found && validate_tracefs_mnt(mnt, TRACEFS_MAGIC))
0092 goto exit_found;
0093
0094 if (block_mount)
0095 return false;
0096
0097 p_info("could not find tracefs, attempting to mount it now");
0098
0099
0100
0101
0102
0103 strcpy(mnt, known_mnts[1]);
0104 if (mount_tracefs(mnt))
0105 return false;
0106
0107 exit_found:
0108 strcat(mnt, pipe_name);
0109 return true;
0110 }
0111
0112 static void exit_tracelog(int signum)
0113 {
0114 fclose(trace_pipe_fd);
0115 free(buff);
0116
0117 if (json_output) {
0118 jsonw_end_array(json_wtr);
0119 jsonw_destroy(&json_wtr);
0120 }
0121
0122 exit(0);
0123 }
0124
0125 int do_tracelog(int argc, char **argv)
0126 {
0127 const struct sigaction act = {
0128 .sa_handler = exit_tracelog
0129 };
0130 char trace_pipe[PATH_MAX];
0131 size_t buff_len = 0;
0132
0133 if (json_output)
0134 jsonw_start_array(json_wtr);
0135
0136 if (!get_tracefs_pipe(trace_pipe))
0137 return -1;
0138
0139 trace_pipe_fd = fopen(trace_pipe, "r");
0140 if (!trace_pipe_fd) {
0141 p_err("could not open trace pipe: %s", strerror(errno));
0142 return -1;
0143 }
0144
0145 sigaction(SIGHUP, &act, NULL);
0146 sigaction(SIGINT, &act, NULL);
0147 sigaction(SIGTERM, &act, NULL);
0148 while (1) {
0149 ssize_t ret;
0150
0151 ret = getline(&buff, &buff_len, trace_pipe_fd);
0152 if (ret <= 0) {
0153 p_err("failed to read content from trace pipe: %s",
0154 strerror(errno));
0155 break;
0156 }
0157 if (json_output)
0158 jsonw_string(json_wtr, buff);
0159 else
0160 printf("%s", buff);
0161 }
0162
0163 fclose(trace_pipe_fd);
0164 free(buff);
0165 return -1;
0166 }