diff --git a/cmds/info.c b/cmds/info.c index a83ce6823..cf4b7f065 100644 --- a/cmds/info.c +++ b/cmds/info.c @@ -853,6 +853,82 @@ static int read_uftrace_version(void *arg) return 0; } +void write_header(int fd, struct uftrace_file_header *hdr) +{ + dprintf(fd, "magic:%s\n", hdr->magic); + dprintf(fd, "version:%u\n", hdr->version); + dprintf(fd, "header_size:%u\n", hdr->header_size); + dprintf(fd, "endian:%u\n", hdr->endian); + dprintf(fd, "elf_class:%u\n", hdr->elf_class); + dprintf(fd, "feat_mask:%"PRIu64"\n", hdr->feat_mask); + dprintf(fd, "info_mask:%"PRIu64"\n", hdr->info_mask); + dprintf(fd, "max_stack:%u\n", hdr->max_stack); +} + +static char *read_header_field(FILE *fp, struct uftrace_file_header *hdr, + const char *field, char *buf) +{ + int len = strlen(field); + + if (fgets(buf, PATH_MAX, fp) == NULL) + return NULL; + if (strncmp(buf, field, len)) + return NULL; + return &buf[len]; +} + +int read_header(struct uftrace_file_header *hdr, FILE *fp, bool is_info_txt) +{ + char buf[PATH_MAX]; + char *data; + + if (is_info_txt) { + data = read_header_field(fp, hdr, "magic:", buf); + if (!data) + return -1; + memcpy(hdr->magic, copy_info_str(data), UFTRACE_MAGIC_LEN - 1); + + data = read_header_field(fp, hdr, "version:", buf); + if (!data) + return -1; + sscanf(data, "%u", &hdr->version); + + data = read_header_field(fp, hdr, "header_size:", buf); + if (!data) + return -1; + sscanf(data, "%hu", &hdr->header_size); + + data = read_header_field(fp, hdr, "endian:", buf); + if (!data) + return -1; + sscanf(data, "%hhu", &hdr->endian); + + data = read_header_field(fp, hdr, "elf_class:", buf); + if (!data) + return -1; + sscanf(data, "%hhu", &hdr->elf_class); + + data = read_header_field(fp, hdr, "feat_mask:", buf); + if (!data) + return -1; + sscanf(data, "%"PRIu64, &hdr->feat_mask); + + data = read_header_field(fp, hdr, "info_mask:", buf); + if (!data) + return -1; + sscanf(data, "%"PRIu64, &hdr->info_mask); + + data = read_header_field(fp, hdr, "max_stack:", buf); + if (!data) + return -1; + sscanf(data, "%hu", &hdr->max_stack); + } + else if (fread(hdr, sizeof(hdr), 1, fp) != 1) + return -1; + return 0; +} + + struct uftrace_info_handler { enum uftrace_info_bits bit; int (*handler)(void *arg); @@ -987,10 +1063,13 @@ void process_uftrace_info(struct uftrace_data *handle, struct opts *opts, if (info_mask == 0) return; - snprintf(buf, sizeof(buf), "%s/info", opts->dirname); + snprintf(buf, sizeof(buf), "%s/info.txt", opts->dirname); - if (stat(buf, &statbuf) < 0) - return; + if (stat(buf, &statbuf) < 0) { + snprintf(buf, sizeof(buf), "%s/info", opts->dirname); + if (stat(buf, &statbuf) < 0) + return; + } process(data, "# system information\n"); process(data, "# ==================\n"); diff --git a/cmds/record.c b/cmds/record.c index a51696df9..0d8870283 100644 --- a/cmds/record.c +++ b/cmds/record.c @@ -421,11 +421,12 @@ static int fill_file_header(struct opts *opts, int status, struct rusage *rusage char *filename = NULL; struct uftrace_file_header hdr; char elf_ident[EI_NIDENT]; + char buf[PATH_MAX]; - xasprintf(&filename, "%s/info", opts->dirname); + xasprintf(&filename, "%s/info.txt", opts->dirname); pr_dbg3("fill header (metadata) info in %s\n", filename); - fd = open(filename, O_WRONLY | O_CREAT| O_TRUNC, 0644); + fd = open(filename, O_RDWR | O_CREAT| O_TRUNC, 0644); if (fd < 0) pr_err("cannot open info file"); @@ -447,26 +448,21 @@ static int fill_file_header(struct opts *opts, int status, struct rusage *rusage hdr.unused1 = 0; hdr.unused2 = 0; - if (write(fd, &hdr, sizeof(hdr)) != (int)sizeof(hdr)) - pr_err("writing header info failed"); - fill_uftrace_info(&hdr.info_mask, fd, opts, status, rusage, elapsed_time); -try_write: - ret = pwrite(fd, &hdr, sizeof(hdr), 0); - if (ret != (int)sizeof(hdr)) { - static int retry = 0; - - if (ret > 0 && retry++ < 3) - goto try_write; + memset(buf, 0, PATH_MAX); + lseek(fd, 0, SEEK_SET); + if (read(fd, buf, PATH_MAX) < 0) + goto close_efd; + lseek(fd, 0, SEEK_SET); + write_header(fd, &hdr); + if (write(fd, buf, strlen(buf)) < 0) { pr_dbg("writing header info failed.\n"); goto close_efd; } - ret = 0; - close_efd: close(efd); close_fd: @@ -1373,10 +1369,14 @@ static void send_info_file(int sock, const char *dirname) void *info; int len; - xasprintf(&filename, "%s/info", dirname); + xasprintf(&filename, "%s/info.txt", dirname); fd = open(filename, O_RDONLY); - if (fd < 0) - pr_err("open info failed"); + if (fd < 0) { + xasprintf(&filename, "%s/info", dirname); + fd = open(filename, O_RDONLY); + if (fd < 0) + pr_err("open info failed"); + } if (fstat(fd, &stbuf) < 0) pr_err("stat info failed"); diff --git a/uftrace.h b/uftrace.h index 89b642343..495e3faa7 100644 --- a/uftrace.h +++ b/uftrace.h @@ -553,6 +553,9 @@ static inline bool has_event_data(struct uftrace_data *handle) struct rusage; + +void write_header(int fd, struct uftrace_file_header *hdr); +int read_header(struct uftrace_file_header *hdr, FILE *fp, bool is_info_txt); void fill_uftrace_info(uint64_t *info_mask, int fd, struct opts *opts, int status, struct rusage *rusage, char *elapsed_time); int read_uftrace_info(uint64_t info_mask, struct uftrace_data *handle); diff --git a/utils/data-file.c b/utils/data-file.c index e8a0f34d3..07354bcc0 100644 --- a/utils/data-file.c +++ b/utils/data-file.c @@ -413,18 +413,28 @@ bool data_is_lp64(struct uftrace_data *handle) int open_info_file(struct opts *opts, struct uftrace_data *handle) { FILE *fp; - char buf[PATH_MAX]; + char info_txt[PATH_MAX]; + char info_bin[PATH_MAX]; + bool is_info_txt = true; int saved_errno = 0; struct stat stbuf; memset(handle, 0, sizeof(*handle)); - snprintf(buf, sizeof(buf), "%s/info", opts->dirname); + snprintf(info_txt, sizeof(info_txt), "%s/info.txt", opts->dirname); - fp = fopen(buf, "rb"); + fp = fopen(info_txt, "r"); if (fp != NULL) goto ok; + snprintf(info_bin, sizeof(info_bin), "%s/info", opts->dirname); + + fp = fopen(info_bin, "rb"); + if (fp != NULL) { + is_info_txt = false; + goto ok; + } + saved_errno = errno; /* provide a better error code for empty/invalid directories */ if (stat(opts->dirname, &stbuf) == 0) @@ -433,28 +443,44 @@ int open_info_file(struct opts *opts, struct uftrace_data *handle) /* if default dirname is failed */ if (!strcmp(opts->dirname, UFTRACE_DIR_NAME)) { /* try again inside the current directory */ + fp = fopen("./info.txt", "r"); + if (fp != NULL) { + opts->dirname = "./"; + goto ok; + } + fp = fopen("./info", "rb"); if (fp != NULL) { opts->dirname = "./"; + is_info_txt = false; goto ok; } /* retry with old default dirname */ - snprintf(buf, sizeof(buf), "%s/info", UFTRACE_DIR_OLD_NAME); - fp = fopen(buf, "rb"); + snprintf(info_txt, sizeof(info_txt), "%s/info.txt", UFTRACE_DIR_OLD_NAME); + fp = fopen(info_txt, "r"); + if (fp != NULL) { + opts->dirname = UFTRACE_DIR_OLD_NAME; + goto ok; + } + + snprintf(info_bin, sizeof(info_bin), "%s/info", UFTRACE_DIR_OLD_NAME); + fp = fopen(info_bin, "rb"); if (fp != NULL) { opts->dirname = UFTRACE_DIR_OLD_NAME; + is_info_txt = false; goto ok; } saved_errno = errno; /* restore original file name for error reporting */ - snprintf(buf, sizeof(buf), "%s/info", opts->dirname); + snprintf(info_txt, sizeof(info_txt), "%s/info.txt", opts->dirname); + snprintf(info_bin, sizeof(info_bin), "%s/info", opts->dirname); } /* data file loading is failed */ - pr_dbg("cannot open %s file\n", buf); + pr_dbg("cannot open %s or %s file\n", info_txt, info_bin); return -saved_errno; ok: @@ -469,7 +495,7 @@ int open_info_file(struct opts *opts, struct uftrace_data *handle) handle->last_perf_idx = -1; INIT_LIST_HEAD(&handle->events); - if (fread(&handle->hdr, sizeof(handle->hdr), 1, fp) != 1) + if (read_header(&handle->hdr, fp, is_info_txt) < 0) pr_err("cannot read header data"); if (memcmp(handle->hdr.magic, UFTRACE_MAGIC_STR, UFTRACE_MAGIC_LEN))