+ /* read a per-client data area */
+ n = fread(&lcd, 1, sizeof(lcd), fp);
+ if (n < sizeof(lcd)) {
+ if (feof(fp))
+ break;
+ fprintf(stderr, "%s: Short read (%d of %d)\n",
+ progname, n, (int)sizeof(lcd));
+ return ferror(fp) ? EIO : EINVAL;
+ }
+
+ if (lcd.lcd_uuid[0] == '\0')
+ continue;
+
+ /* swab structure fields */
+ lcd.lcd_last_transno =
+ __le64_to_cpu(lcd.lcd_last_transno);
+ lcd.lcd_last_xid = __le64_to_cpu(lcd.lcd_last_xid);
+ lcd.lcd_last_result = __le32_to_cpu(lcd.lcd_last_result);
+ lcd.lcd_last_data = __le32_to_cpu(lcd.lcd_last_data);
+ lcd.lcd_generation = __le32_to_cpu(lcd.lcd_generation);
+
+ /* display per-client data area */
+ printf("\n %.40s:\n", lcd.lcd_uuid);
+ printf(" generation: %u\n", lcd.lcd_generation);
+ printf(" last_transaction: %llu\n",
+ (unsigned long long)lcd.lcd_last_transno);
+ printf(" last_xid: %llu\n",
+ (unsigned long long)lcd.lcd_last_xid);
+ printf(" last_result: %u\n", lcd.lcd_last_result);
+ printf(" last_data: %u\n", lcd.lcd_last_data);
+
+ if (lcd.lcd_last_close_transno != 0 &&
+ lcd.lcd_last_close_xid != 0) {
+ lcd.lcd_last_close_transno =
+ __le64_to_cpu(lcd.lcd_last_close_transno);
+ lcd.lcd_last_close_xid =
+ __le64_to_cpu(lcd.lcd_last_close_xid);
+ lcd.lcd_last_close_result =
+ __le32_to_cpu(lcd.lcd_last_close_result);
+ lcd.lcd_last_close_data =
+ __le32_to_cpu(lcd.lcd_last_close_data);
+ printf(" last_close_transation: %llu\n",
+ (unsigned long long)lcd.lcd_last_close_transno);
+ printf(" last_close_xid: %llu\n",
+ (unsigned long long)lcd.lcd_last_close_xid);
+ printf(" last_close_result: %u\n",
+ lcd.lcd_last_close_result);
+ printf(" last_close_data: %u\n",
+ lcd.lcd_last_close_data);
+ }
+ }
+
+ return 0;
+}
+
+int print_reply_data(FILE *fp)
+{
+ struct lsd_reply_header lrh = {};
+ unsigned long long slot;
+ int rc = 0;
+ int n;
+
+ /* read reply_data header */
+ printf("\n%s:\n", REPLY_DATA);
+ n = fread(&lrh, 1, sizeof(lrh), fp);
+ if (n < sizeof(lrh)) {
+ fprintf(stderr, "%s: Short read (%d of %d)\n",
+ progname, n, (int)sizeof(lrh));
+ rc = ferror(fp) ? EIO : EINVAL;
+ }
+
+ /* check header */
+ lrh.lrh_magic = __le32_to_cpu(lrh.lrh_magic);
+ lrh.lrh_header_size = __le32_to_cpu(lrh.lrh_header_size);
+ lrh.lrh_reply_size = __le32_to_cpu(lrh.lrh_reply_size);
+ if (lrh.lrh_magic != LRH_MAGIC) {
+ fprintf(stderr,
+ "%s: invalid %s header: lrh_magic=0x%08x expected 0x%08x\n",
+ progname, REPLY_DATA, lrh.lrh_magic, LRH_MAGIC);
+ rc = EINVAL;
+ }
+ if (lrh.lrh_header_size != sizeof(struct lsd_reply_header)) {
+ fprintf(stderr,
+ "%s: invalid %s header: lrh_header_size=0x%08x expected 0x%08x\n",
+ progname, REPLY_DATA, lrh.lrh_header_size,
+ (unsigned int)sizeof(struct lsd_reply_header));
+ rc = EINVAL;
+ }
+ if (lrh.lrh_reply_size != sizeof(struct lsd_reply_data)) {
+ fprintf(stderr,
+ "%s: invalid %s header: lrh_reply_size=0x%08x expected 0x%08x\n",
+ progname, REPLY_DATA, lrh.lrh_reply_size,
+ (unsigned int)sizeof(struct lsd_reply_data));
+ rc = EINVAL;
+ }
+
+ if (rc) {
+ /* dump header */
+ fprintf(stderr, "lsd_reply_header:\n");
+ fprintf(stderr, "\tlrh_magic: 0x%08x\n", lrh.lrh_magic);
+ fprintf(stderr, "\tlrh_header_size: %u\n", lrh.lrh_header_size);
+ fprintf(stderr, "\tlrh_reply_size: %u\n", lrh.lrh_reply_size);
+ return rc;
+ }
+
+ /* walk throuh the reply data */
+ for (slot = 0; ; slot++) {
+ struct lsd_reply_data lrd;
+
+ /* read a reply data */
+ n = fread(&lrd, 1, sizeof(lrd), fp);
+ if (n < sizeof(lrd)) {
+ if (feof(fp))
+ break;
+ fprintf(stderr, "%s: Short read (%d of %d)\n",
+ progname, n, (int)sizeof(lrd));
+ return ferror(fp) ? EIO : EINVAL;
+ }
+
+ /* display reply data */
+ lrd.lrd_transno = __le64_to_cpu(lrd.lrd_transno);
+ lrd.lrd_xid = __le64_to_cpu(lrd.lrd_xid);
+ lrd.lrd_data = __le64_to_cpu(lrd.lrd_data);
+ lrd.lrd_result = __le32_to_cpu(lrd.lrd_result);
+ lrd.lrd_client_gen = __le32_to_cpu(lrd.lrd_client_gen);
+
+ printf(" %lld:\n", slot);
+ printf(" client_generation: %u\n",
+ lrd.lrd_client_gen);
+ printf(" last_transaction: %lluu\n",
+ (unsigned long long)lrd.lrd_transno);
+ printf(" last_xid: %llu\n",
+ (unsigned long long)lrd.lrd_xid);
+ printf(" last_result: %u\n", lrd.lrd_result);
+ printf(" last_data: %llu\n\n",
+ (unsigned long long)lrd.lrd_data);
+ }
+
+ return 0;
+}
+
+void display_usage(void)
+{
+ printf("Usage: %s [OPTIONS] devicename\n", progname);
+ printf("Usage: %s [OPTIONS] -C <last_rcvd_file> -R <reply_data_file>\n",
+ progname);
+ printf("Read and print the last_rcvd/reply_data file from a device\n");
+ printf("(safe for mounted devices) or from a file\n");
+ printf("\t-c, --client, display client information\n");
+ printf("\t-h, --help, display this help and exit\n");
+ printf("\t-r, --reply, display reply data information\n");
+ printf("\t-C FILE, --last_rcvd=FILE, specify FILE as input for client information\n");
+ printf("\t-R FILE, --reply_data=FILE, specify FILE as input for reply information\n");
+}