1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <stdio.h>
18 #include <sys/time.h>
19 #include <sys/types.h>
20 #include <unistd.h>
21 #include <stdlib.h>
22 #include <signal.h>
23 #include <string.h>
24 #include <sys/stat.h>
25 #include <sys/errno.h>
26 #include <fcntl.h>
27 #include <ctype.h>
28 #include <endian.h>
29 #include "ioshark.h"
30 
31 char *progname;
32 
33 struct ioshark_header_old {
34 	int	num_files;
35 	int	num_io_operations;
36 };
37 
38 struct ioshark_file_operation_old {
39 	/* delta us between previous file op and this */
40 	u_int64_t		delta_us;
41 	enum file_op		file_op;
42 	int			fileno;
43 	union {
44 		struct lseek_args_old {
45 #define lseek_offset_old	u.lseek_a.offset
46 #define lseek_action_old	u.lseek_a.action
47 			off_t	offset;
48 			int action;
49 		} lseek_a;
50 		struct prw_args_old {
51 #define prw_offset_old		u.prw_a.offset
52 #define prw_len_old		u.prw_a.len
53 			off_t	offset;
54 			size_t	len;
55 		} prw_a;
56 #define rw_len_old		u.rw_a.len
57 		struct rw_args_old {
58 			size_t	len;
59 		} rw_a;
60 #define mmap_offset_old		u.mmap_a.offset
61 #define mmap_len_old		u.mmap_a.len
62 #define mmap_prot_old		u.mmap_a.prot
63 		struct mmap_args_old {
64 			off_t	offset;
65 			size_t	len;
66 			int	prot;
67 	} mmap_a;
68 #define open_flags_old		u.open_a.flags
69 #define open_mode_old		u.open_a.mode
70 		struct open_args_old {
71 			int	flags;
72 			mode_t	mode;
73 		} open_a;
74 	} u;
75 };
76 
77 struct ioshark_file_state_old {
78 	int	fileno;	/* 1..num_files, with files name ioshark.<fileno> */
79 	size_t	size;
80 	int	global_filename_ix;
81 };
82 
usage(void)83 void usage(void)
84 {
85 	fprintf(stderr, "%s in_file out_file\n", progname);
86 }
87 
main(int argc,char ** argv)88 int main(int argc, char **argv)
89 {
90 	FILE *old_fp, *new_fp;
91 	char *infile, *outfile;
92 	struct ioshark_header new_header;
93 	struct ioshark_file_operation new_disk_file_op;
94 	struct ioshark_header_old old_header;
95 	struct ioshark_file_operation_old old_disk_file_op;
96 	struct ioshark_file_state new_file_state;
97 	struct ioshark_file_state_old old_file_state;
98 	struct stat st;
99 	int i;
100 	u_int64_t aggr_old_file_size = 0;
101 	u_int64_t aggr_new_file_size = 0;
102 
103 	progname = argv[0];
104 	if (argc != 3) {
105 		usage();
106 		exit(EXIT_FAILURE);
107 	}
108 	infile = argv[1];
109 	outfile = argv[2];
110 	if (stat(infile, &st) < 0) {
111 		fprintf(stderr, "%s Can't stat %s\n",
112 			progname, infile);
113 		exit(EXIT_FAILURE);
114 	}
115 	if (st.st_size == 0) {
116 		fprintf(stderr, "%s Empty file %s\n",
117 			progname, infile);
118 		exit(EXIT_FAILURE);
119 	}
120 	old_fp = fopen(infile, "r");
121 	if (old_fp == NULL) {
122 		fprintf(stderr, "%s Can't open %s\n",
123 			progname, infile);
124 		exit(EXIT_FAILURE);
125 	}
126 	new_fp = fopen(outfile, "w+");
127 	if (new_fp == NULL) {
128 		fprintf(stderr, "%s Can't open outfile\n",
129 			progname);
130 		exit(EXIT_FAILURE);
131 	}
132 	/* Convert header */
133 	if (fread(&old_header, sizeof(struct ioshark_header_old),
134 		  1, old_fp) != 1) {
135 		fprintf(stderr,
136 			"%s Read error Header\n",
137 			progname);
138 		exit(EXIT_FAILURE);
139 	}
140 	new_header.version = IOSHARK_VERSION;
141 	new_header.num_files = old_header.num_files;
142 	new_header.num_io_operations = old_header.num_io_operations;
143 	new_header.version = htobe64(new_header.version);
144 	new_header.num_files = htobe64(new_header.num_files);
145 	new_header.num_io_operations =
146 		htobe64(new_header.num_io_operations);
147 	if (fwrite(&new_header, sizeof(struct ioshark_header),
148 		   1, new_fp) != 1) {
149 		fprintf(stderr,
150 			"%s Write error Header\n",
151 			progname);
152 		exit(EXIT_FAILURE);
153 	}
154 	for (i = 0 ; i < old_header.num_files ; i++) {
155 		if (fread(&old_file_state,
156 			  sizeof(struct ioshark_file_state_old),
157 			  1, old_fp) != 1) {
158 			fprintf(stderr,
159 				"%s Read error file state\n",
160 				progname);
161 			exit(EXIT_FAILURE);
162 		}
163 		new_file_state.fileno = old_file_state.fileno;
164 		new_file_state.size = old_file_state.size;
165 		aggr_old_file_size += old_file_state.size;
166 		new_file_state.global_filename_ix =
167 			old_file_state.global_filename_ix;
168 		new_file_state.fileno = htobe64(new_file_state.fileno);
169 		new_file_state.size = htobe64(new_file_state.size);
170 		aggr_new_file_size += be64toh(new_file_state.size);
171 		new_file_state.global_filename_ix =
172 			htobe64(new_file_state.global_filename_ix);
173 		if (fwrite(&new_file_state,
174 			   sizeof(struct ioshark_file_state), 1, new_fp) != 1) {
175 			fprintf(stderr,
176 				"%s Write error file state\n",
177 				progname);
178 			exit(EXIT_FAILURE);
179 		}
180 	}
181 	if (aggr_new_file_size != aggr_old_file_size) {
182 		fprintf(stderr,
183 			"%s Aggr file size mismath %lu != %lu\n",
184 			progname, aggr_new_file_size, aggr_old_file_size);
185 		exit(EXIT_FAILURE);
186 	}
187 
188 	for (i = 0 ; i < old_header.num_io_operations ; i++) {
189 		enum file_op op;
190 
191 		if (fread(&old_disk_file_op,
192 			  sizeof(struct ioshark_file_operation_old),
193 			  1, old_fp) != 1)  {
194 			fprintf(stderr,
195 				"%s Read error file op\n",
196 				progname);
197 			exit(EXIT_FAILURE);
198 		}
199 		op = old_disk_file_op.file_op;
200 		new_disk_file_op.delta_us = old_disk_file_op.delta_us;
201 		new_disk_file_op.delta_us =
202 			htobe64(new_disk_file_op.delta_us);
203 		new_disk_file_op.ioshark_io_op = op;
204 		new_disk_file_op.op_union.enum_size =
205 			htobe32(new_disk_file_op.op_union.enum_size);
206 		new_disk_file_op.fileno = old_disk_file_op.fileno;
207 		new_disk_file_op.fileno = htobe64(new_disk_file_op.fileno);
208 		switch (op) {
209 		case IOSHARK_LSEEK:
210 		case IOSHARK_LLSEEK:
211 			new_disk_file_op.lseek_offset =
212 				old_disk_file_op.lseek_offset_old;
213 			new_disk_file_op.lseek_action =
214 				old_disk_file_op.lseek_action_old;
215 			new_disk_file_op.lseek_offset =
216 				htobe64(new_disk_file_op.lseek_offset);
217 			new_disk_file_op.lseek_action =
218 				htobe32(new_disk_file_op.lseek_action);
219 			break;
220 		case IOSHARK_PREAD64:
221 		case IOSHARK_PWRITE64:
222 			new_disk_file_op.prw_offset =
223 				old_disk_file_op.prw_offset_old;
224 			new_disk_file_op.prw_len =
225 				old_disk_file_op.prw_len_old;
226 			new_disk_file_op.prw_offset =
227 				htobe64(new_disk_file_op.prw_offset);
228 			new_disk_file_op.prw_len =
229 				htobe64(new_disk_file_op.prw_len);
230 			break;
231 		case IOSHARK_READ:
232 		case IOSHARK_WRITE:
233 			new_disk_file_op.rw_len =
234 				old_disk_file_op.rw_len_old;
235 			new_disk_file_op.rw_len =
236 				htobe64(new_disk_file_op.rw_len);
237 			break;
238 		case IOSHARK_MMAP:
239 		case IOSHARK_MMAP2:
240 			new_disk_file_op.mmap_offset =
241 				old_disk_file_op.mmap_offset_old;
242 			new_disk_file_op.mmap_len =
243 				old_disk_file_op.mmap_len_old;
244 			new_disk_file_op.mmap_prot =
245 				old_disk_file_op.mmap_prot;
246 			new_disk_file_op.mmap_offset =
247 				htobe64(new_disk_file_op.mmap_offset);
248 			new_disk_file_op.mmap_len =
249 				htobe64(new_disk_file_op.mmap_len);
250 			new_disk_file_op.mmap_prot =
251 				htobe32(new_disk_file_op.mmap_prot);
252 			break;
253 		case IOSHARK_OPEN:
254 			new_disk_file_op.open_flags =
255 				old_disk_file_op.open_flags_old;
256 			new_disk_file_op.open_mode =
257 				old_disk_file_op.open_mode_old;
258 			new_disk_file_op.open_flags =
259 				htobe32(new_disk_file_op.open_flags);
260 			new_disk_file_op.open_mode =
261 				htobe32(new_disk_file_op.open_mode);
262 			break;
263 		case IOSHARK_FSYNC:
264 		case IOSHARK_FDATASYNC:
265 			break;
266 		case IOSHARK_CLOSE:
267 			break;
268 		default:
269 			fprintf(stderr, "%s: unknown FILE_OP %d\n",
270 				progname, op);
271 			exit(EXIT_FAILURE);
272 			break;
273 		}
274 		if (fwrite(&new_disk_file_op,
275 			   sizeof(struct ioshark_file_operation),
276 			   1, new_fp) != 1) {
277 			fprintf(stderr,
278 				"%s Write error file op\n",
279 				progname);
280 			exit(EXIT_FAILURE);
281 		}
282 	}
283 }
284