Merge branch 'alex'
[nbd.git] / nbd-trdump.c
1 /*
2  * nbd-trdump.c
3  *
4  * Takes an nbd transaction log file on stdin and translates it into something
5  * comprehensible
6  */
7
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <sys/time.h>
12 #include <sys/types.h>
13 #include <stdint.h>
14 #include <unistd.h>
15 #include "config.h"
16 #include "cliserv.h"
17 #include "nbd.h"
18
19 static inline void doread(int f, void *buf, size_t len) {
20         ssize_t res;
21
22         while(len>0) {
23                 if((res=read(f, buf, len)) <=0) {
24                         if (!res)
25                                 exit(0);
26                         perror ("Error reading transactions");
27                         exit(1);
28                 }
29                 len-=res;
30                 buf+=res;
31         }
32 }
33
34 int main(int argc, char**argv) {
35         struct nbd_request req;
36         struct nbd_reply rep;
37         uint32_t magic;
38         uint64_t handle;
39         uint32_t error;
40         uint32_t command;
41         uint32_t len;
42         uint64_t offset;
43         char * ctext;
44         int readfd = 0; /* stdin */
45
46         if(argc > 1) {
47                 int retval=0;
48                 if(strcmp(argv[1], "--help") && strcmp(argv[1], "-h")) {
49                         printf("E: unknown option %s.\n", argv[1]);
50                         retval=1;
51                 }
52                 printf("This is nbd-trdump, part of nbd %s.\n", PACKAGE_VERSION);
53                 printf("Use: %s < transactionlog\n", argv[0]);
54                 return retval;
55         }
56
57         while (1) {
58                 /* Read a request or reply from the transaction file */
59                 doread(readfd, &magic, sizeof(magic));
60                 magic = ntohl(magic);
61                 switch (magic) {
62                 case NBD_REQUEST_MAGIC:
63                         doread(readfd, sizeof(magic)+(char *)(&req), sizeof(struct nbd_request)-sizeof(magic));
64                         handle = ntohll(*((long long int *)(req.handle)));
65                         offset = ntohll(req.from);
66                         len = ntohl(req.len);
67                         command = ntohl(req.type);
68                         
69                         switch (command & NBD_CMD_MASK_COMMAND) {
70                         case NBD_CMD_READ:
71                                 ctext="NBD_CMD_READ";
72                                 break;
73                         case NBD_CMD_WRITE:
74                                 ctext="NBD_CMD_WRITE";
75                                 break;
76                         case NBD_CMD_DISC:
77                                 ctext="NBD_CMD_DISC";
78                                 break;
79                         case NBD_CMD_FLUSH:
80                                 ctext="NBD_CMD_FLUSH";
81                                 break;
82                         default:
83                                 ctext="UNKNOWN";
84                                 break;
85                         }
86                         printf("> H=%016llx C=0x%08x (%13s+%4s) O=%016llx L=%08x\n",
87                                (long long unsigned int) handle,
88                                command,
89                                ctext,
90                                (command & NBD_CMD_FLAG_FUA)?"FUA":"NONE",
91                                (long long unsigned int) offset,
92                                len);
93                         
94                         break;
95                 case NBD_REPLY_MAGIC:
96                         doread(readfd, sizeof(magic)+(char *)(&rep), sizeof(struct nbd_reply)-sizeof(magic));
97                         handle = ntohll(*((long long int *)(rep.handle)));
98                         error = ntohl(rep.error);
99                         
100                         printf("< H=%016llx E=0x%08x\n",
101                                (long long unsigned int) handle,
102                                error);
103                         break;
104                         
105                 default:
106                         printf("? Unknown transaction type %08x\n",magic);
107                         break;
108                 }
109                 
110         }
111         /* never reached */
112         return 0;
113 }