/* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <stdio.h> #include <sys/time.h> #include <sys/types.h> #include <unistd.h> #include <stdlib.h> #include <signal.h> #include <string.h> #include <sys/stat.h> #include <sys/errno.h> #include <fcntl.h> #include <ctype.h> #include <endian.h> #include "ioshark.h" char *progname; struct ioshark_header_old { int num_files; int num_io_operations; }; struct ioshark_file_operation_old { /* delta us between previous file op and this */ u_int64_t delta_us; enum file_op file_op; int fileno; union { struct lseek_args_old { #define lseek_offset_old u.lseek_a.offset #define lseek_action_old u.lseek_a.action off_t offset; int action; } lseek_a; struct prw_args_old { #define prw_offset_old u.prw_a.offset #define prw_len_old u.prw_a.len off_t offset; size_t len; } prw_a; #define rw_len_old u.rw_a.len struct rw_args_old { size_t len; } rw_a; #define mmap_offset_old u.mmap_a.offset #define mmap_len_old u.mmap_a.len #define mmap_prot_old u.mmap_a.prot struct mmap_args_old { off_t offset; size_t len; int prot; } mmap_a; #define open_flags_old u.open_a.flags #define open_mode_old u.open_a.mode struct open_args_old { int flags; mode_t mode; } open_a; } u; }; struct ioshark_file_state_old { int fileno; /* 1..num_files, with files name ioshark.<fileno> */ size_t size; int global_filename_ix; }; void usage(void) { fprintf(stderr, "%s in_file out_file\n", progname); } int main(int argc, char **argv) { FILE *old_fp, *new_fp; char *infile, *outfile; struct ioshark_header new_header; struct ioshark_file_operation new_disk_file_op; struct ioshark_header_old old_header; struct ioshark_file_operation_old old_disk_file_op; struct ioshark_file_state new_file_state; struct ioshark_file_state_old old_file_state; struct stat st; int i; u_int64_t aggr_old_file_size = 0; u_int64_t aggr_new_file_size = 0; progname = argv[0]; if (argc != 3) { usage(); exit(EXIT_FAILURE); } infile = argv[1]; outfile = argv[2]; if (stat(infile, &st) < 0) { fprintf(stderr, "%s Can't stat %s\n", progname, infile); exit(EXIT_FAILURE); } if (st.st_size == 0) { fprintf(stderr, "%s Empty file %s\n", progname, infile); exit(EXIT_FAILURE); } old_fp = fopen(infile, "r"); if (old_fp == NULL) { fprintf(stderr, "%s Can't open %s\n", progname, infile); exit(EXIT_FAILURE); } new_fp = fopen(outfile, "w+"); if (new_fp == NULL) { fprintf(stderr, "%s Can't open outfile\n", progname); exit(EXIT_FAILURE); } /* Convert header */ if (fread(&old_header, sizeof(struct ioshark_header_old), 1, old_fp) != 1) { fprintf(stderr, "%s Read error Header\n", progname); exit(EXIT_FAILURE); } new_header.version = IOSHARK_VERSION; new_header.num_files = old_header.num_files; new_header.num_io_operations = old_header.num_io_operations; new_header.version = htobe64(new_header.version); new_header.num_files = htobe64(new_header.num_files); new_header.num_io_operations = htobe64(new_header.num_io_operations); if (fwrite(&new_header, sizeof(struct ioshark_header), 1, new_fp) != 1) { fprintf(stderr, "%s Write error Header\n", progname); exit(EXIT_FAILURE); } for (i = 0 ; i < old_header.num_files ; i++) { if (fread(&old_file_state, sizeof(struct ioshark_file_state_old), 1, old_fp) != 1) { fprintf(stderr, "%s Read error file state\n", progname); exit(EXIT_FAILURE); } new_file_state.fileno = old_file_state.fileno; new_file_state.size = old_file_state.size; aggr_old_file_size += old_file_state.size; new_file_state.global_filename_ix = old_file_state.global_filename_ix; new_file_state.fileno = htobe64(new_file_state.fileno); new_file_state.size = htobe64(new_file_state.size); aggr_new_file_size += be64toh(new_file_state.size); new_file_state.global_filename_ix = htobe64(new_file_state.global_filename_ix); if (fwrite(&new_file_state, sizeof(struct ioshark_file_state), 1, new_fp) != 1) { fprintf(stderr, "%s Write error file state\n", progname); exit(EXIT_FAILURE); } } if (aggr_new_file_size != aggr_old_file_size) { fprintf(stderr, "%s Aggr file size mismath %lu != %lu\n", progname, aggr_new_file_size, aggr_old_file_size); exit(EXIT_FAILURE); } for (i = 0 ; i < old_header.num_io_operations ; i++) { enum file_op op; if (fread(&old_disk_file_op, sizeof(struct ioshark_file_operation_old), 1, old_fp) != 1) { fprintf(stderr, "%s Read error file op\n", progname); exit(EXIT_FAILURE); } op = old_disk_file_op.file_op; new_disk_file_op.delta_us = old_disk_file_op.delta_us; new_disk_file_op.delta_us = htobe64(new_disk_file_op.delta_us); new_disk_file_op.ioshark_io_op = op; new_disk_file_op.op_union.enum_size = htobe32(new_disk_file_op.op_union.enum_size); new_disk_file_op.fileno = old_disk_file_op.fileno; new_disk_file_op.fileno = htobe64(new_disk_file_op.fileno); switch (op) { case IOSHARK_LSEEK: case IOSHARK_LLSEEK: new_disk_file_op.lseek_offset = old_disk_file_op.lseek_offset_old; new_disk_file_op.lseek_action = old_disk_file_op.lseek_action_old; new_disk_file_op.lseek_offset = htobe64(new_disk_file_op.lseek_offset); new_disk_file_op.lseek_action = htobe32(new_disk_file_op.lseek_action); break; case IOSHARK_PREAD64: case IOSHARK_PWRITE64: new_disk_file_op.prw_offset = old_disk_file_op.prw_offset_old; new_disk_file_op.prw_len = old_disk_file_op.prw_len_old; new_disk_file_op.prw_offset = htobe64(new_disk_file_op.prw_offset); new_disk_file_op.prw_len = htobe64(new_disk_file_op.prw_len); break; case IOSHARK_READ: case IOSHARK_WRITE: new_disk_file_op.rw_len = old_disk_file_op.rw_len_old; new_disk_file_op.rw_len = htobe64(new_disk_file_op.rw_len); break; case IOSHARK_MMAP: case IOSHARK_MMAP2: new_disk_file_op.mmap_offset = old_disk_file_op.mmap_offset_old; new_disk_file_op.mmap_len = old_disk_file_op.mmap_len_old; new_disk_file_op.mmap_prot = old_disk_file_op.mmap_prot; new_disk_file_op.mmap_offset = htobe64(new_disk_file_op.mmap_offset); new_disk_file_op.mmap_len = htobe64(new_disk_file_op.mmap_len); new_disk_file_op.mmap_prot = htobe32(new_disk_file_op.mmap_prot); break; case IOSHARK_OPEN: new_disk_file_op.open_flags = old_disk_file_op.open_flags_old; new_disk_file_op.open_mode = old_disk_file_op.open_mode_old; new_disk_file_op.open_flags = htobe32(new_disk_file_op.open_flags); new_disk_file_op.open_mode = htobe32(new_disk_file_op.open_mode); break; case IOSHARK_FSYNC: case IOSHARK_FDATASYNC: break; case IOSHARK_CLOSE: break; default: fprintf(stderr, "%s: unknown FILE_OP %d\n", progname, op); exit(EXIT_FAILURE); break; } if (fwrite(&new_disk_file_op, sizeof(struct ioshark_file_operation), 1, new_fp) != 1) { fprintf(stderr, "%s Write error file op\n", progname); exit(EXIT_FAILURE); } } }