Guest User

Untitled

a guest
Feb 12th, 2011
271
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 7.98 KB | None | 0 0
  1. /*
  2. Copying and distribution of this file, with or without modification,
  3. are permitted in any medium without royalty.  This file is offered
  4. as-is, without any warranty.
  5. */
  6.  
  7. import java.io.FileInputStream;
  8. import java.io.FileNotFoundException;
  9. import java.io.IOException;
  10. import java.math.BigInteger;
  11. import java.nio.BufferUnderflowException;
  12. import java.nio.ByteBuffer;
  13. import java.nio.ByteOrder;
  14. import java.nio.MappedByteBuffer;
  15. import java.nio.channels.FileChannel;
  16. import java.nio.channels.FileChannel.MapMode;
  17. import java.util.ArrayList;
  18. import java.util.Arrays;
  19.  
  20.  
  21. public class ZfsReader {
  22.     public static void main(String[] argv) {
  23.         if (argv.length != 1) {
  24.             System.err.println("Usage <app> <vdev file>");
  25.             System.exit(1);
  26.             return;
  27.         }
  28.        
  29.         FileInputStream in;
  30.         try {
  31.             in = new FileInputStream(argv[0]);
  32.         } catch (FileNotFoundException e) {
  33.             System.err.println(e.getLocalizedMessage());
  34.             System.exit(1);
  35.             return;
  36.         }
  37.        
  38.         FileChannel channel = in.getChannel();
  39.         try {
  40.             try {
  41.                 for (int i = 0; i < 4; i++) {
  42.                     VdevLabel vdevLabel = new VdevLabel(channel, i);
  43.                    
  44.                     Uberblock mostRecent = null;
  45.                     for (Uberblock uberblock : vdevLabel.getUberblocks()) {
  46.                         if (uberblock != null &&
  47.                                 (mostRecent == null || uberblock.getTransactionGroup().compareTo(mostRecent.getTransactionGroup()) > 0)) {
  48.                             mostRecent = uberblock;
  49.                         }
  50.                     }
  51.                    
  52.                     System.out.printf("vdev base: 0x%x\n", vdevLabel.getBase());
  53.                     if (mostRecent != null) {
  54.                         System.out.printf("  uberblock offset: 0x%x, txn group = %d, sum = %d\n", mostRecent.getOffset(), mostRecent.getTransactionGroup(), mostRecent.getGuidSum());
  55.                     } else {
  56.                         System.out.printf("  no valid uberblocks found\n");
  57.                     }
  58.                 }
  59.                
  60.             } finally {
  61.                 channel.close();
  62.             }
  63.         } catch (IOException e) {
  64.            
  65.         }
  66.     }
  67.    
  68.     public static class BlockPointer extends ZfsStruct {
  69.  
  70.         //dva_t           blk_dva[3];     /* 128-bit Data Virtual Address */
  71.         //uint64_t        blk_prop;       /* size, compression, type, etc */
  72.         //uint64_t        blk_pad[3];     /* Extra space for the future   */
  73.         //uint64_t        blk_birth;      /* transaction group at birth   */
  74.         //uint64_t        blk_fill;       /* fill count                   */
  75.         //zio_cksum_t     blk_cksum;      /* 256-bit checksum             */
  76.  
  77.         private final BigInteger[] dataVirtualAddress = new BigInteger[3];
  78.         private final BigInteger blockProperties;
  79.         private final long[] pad = new long[3];
  80.         private final BigInteger blockBirth;
  81.         private final BigInteger blockFillCount;
  82.         private final byte[] blockChecksum = new byte[32];
  83.        
  84.         public BlockPointer(ByteBuffer buffer) {
  85.             dataVirtualAddress[0] = getUnsignedBigInteger(buffer, 16);
  86.             dataVirtualAddress[1] = getUnsignedBigInteger(buffer, 16);
  87.             dataVirtualAddress[2] = getUnsignedBigInteger(buffer, 16);
  88.            
  89.             blockProperties = getUnsignedBigInteger(buffer, 8);
  90.            
  91.             pad[0] = buffer.getLong();
  92.             pad[1] = buffer.getLong();
  93.             pad[2] = buffer.getLong();
  94.            
  95.             blockBirth = getUnsignedBigInteger(buffer, 8);
  96.             blockFillCount = getUnsignedBigInteger(buffer, 8);
  97.            
  98.             buffer.get(blockChecksum);
  99.         }
  100.  
  101.         public BigInteger[] getDataVirtualAddress() {
  102.             return dataVirtualAddress;
  103.         }
  104.  
  105.         public BigInteger getBlockProperties() {
  106.             return blockProperties;
  107.         }
  108.  
  109.         public long[] getPad() {
  110.             return pad;
  111.         }
  112.  
  113.         public BigInteger getBlockBirth() {
  114.             return blockBirth;
  115.         }
  116.  
  117.         public BigInteger getBlockFillCount() {
  118.             return blockFillCount;
  119.         }
  120.  
  121.         public byte[] getBlockChecksum() {
  122.             return blockChecksum;
  123.         }
  124.     }
  125.    
  126.  
  127.     public static class InvalidBlockException extends Exception {
  128.  
  129.         private static final long serialVersionUID = 1286497411777506847L;
  130.  
  131.         public InvalidBlockException() {
  132.            
  133.         }
  134.        
  135.         public InvalidBlockException(String message) {
  136.             super(message);
  137.         }
  138.     }
  139.    
  140.     public static class Uberblock extends ZfsStruct {
  141.         private static final byte[] BIG_ENDIAN_MAGIC = new byte[] {
  142.             (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
  143.             (byte)0x00, (byte)0xba, (byte)0xb1, (byte)0x0c
  144.         };
  145.        
  146.         private static final byte[] LITTLE_ENDIAN_MAGIC = new byte[] {
  147.             (byte)0x0c, (byte)0xb1, (byte)0xba, (byte)0x00,
  148.             (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00
  149.         };
  150.        
  151.         private static final int UBERBLOCK_SIZE = 1024;
  152.        
  153.         private final int offset;
  154.         private long uberblockVersion;
  155.         private BigInteger transactionGroup;
  156.         private BigInteger guidSum;
  157.         private long timestamp;
  158.         private BlockPointer blockPointer;
  159.        
  160.         public Uberblock(ByteBuffer buffer) throws InvalidBlockException {
  161.             offset = buffer.position();
  162.            
  163.             byte[] magic = new byte[8];
  164.             buffer.get(magic);
  165.            
  166.             ByteOrder byteOrder = null;
  167.            
  168.             if (Arrays.equals(BIG_ENDIAN_MAGIC, magic)) {
  169.                 byteOrder = ByteOrder.BIG_ENDIAN;
  170.                 buffer.order(byteOrder);
  171.             } else if (Arrays.equals(LITTLE_ENDIAN_MAGIC, magic)) {
  172.                 byteOrder = ByteOrder.LITTLE_ENDIAN;
  173.                 buffer.order(byteOrder);
  174.             }
  175.  
  176.             uberblockVersion = buffer.getLong();
  177.             transactionGroup = getUnsignedBigInteger(buffer, 8);
  178.             guidSum = getUnsignedBigInteger(buffer, 8);
  179.             timestamp = buffer.getLong();
  180.             blockPointer = new BlockPointer(buffer);
  181.            
  182.             buffer.position(offset + UBERBLOCK_SIZE);
  183.            
  184.             if (byteOrder == null) {
  185.                 throw new InvalidBlockException("No ZFS Magic");
  186.             }
  187.         }
  188.  
  189.         public long getUberblockVersion() {
  190.             return uberblockVersion;
  191.         }
  192.  
  193.         public BigInteger getTransactionGroup() {
  194.             return transactionGroup;
  195.         }
  196.  
  197.         public BigInteger getGuidSum() {
  198.             return guidSum;
  199.         }
  200.  
  201.         public long getTimestamp() {
  202.             return timestamp;
  203.         }
  204.        
  205.         public BlockPointer getBlockPointer() {
  206.             return blockPointer;
  207.         }
  208.        
  209.         public int getOffset() {
  210.             return offset;
  211.         }
  212.     }
  213.    
  214.     public static class VdevLabel {
  215.         private static final int VDEV_LABEL_SIZE = 256 * 1024;
  216.         private static final int FIRST_UBERBLOCK = 128 * 1024;
  217.         private static final int LAST_UBERBLOCK = 256 * 1024;
  218.        
  219.         private final Uberblock[] uberblocks;
  220.        
  221.         private final long base;
  222.        
  223.         // 0x00 - 0x1FFF: blank
  224.         // 0x2000 - 0x3FFF: Boot Header (reserved)
  225.         // 0x4000 - 0x1FFFF: Name/Value pairs
  226.         // 0x20000 - 0x3ffff: Uberblock array
  227.        
  228.        
  229.         public VdevLabel(FileChannel channel, int labelIndex) throws IOException {
  230.             if (labelIndex >= 4 || labelIndex < 0) {
  231.                 throw new IllegalArgumentException();
  232.             }
  233.            
  234.             if (channel.size() < VDEV_LABEL_SIZE * 4) {
  235.                 throw new IOException("Vdev not big enough");
  236.             }
  237.            
  238.             MappedByteBuffer buffer;
  239.            
  240.             if (labelIndex < 2) {
  241.                 base = VDEV_LABEL_SIZE * labelIndex;
  242.             } else {
  243.                 base = channel.size() - VDEV_LABEL_SIZE * (4 - labelIndex);
  244.             }
  245.            
  246.             buffer = channel.map(MapMode.READ_ONLY, base, VDEV_LABEL_SIZE);
  247.            
  248.             ArrayList<Uberblock> uberblockList = new ArrayList<Uberblock>(128);
  249.            
  250.             for (buffer.position(FIRST_UBERBLOCK); buffer.position() < LAST_UBERBLOCK;) {
  251.                 try {
  252.                     uberblockList.add(new Uberblock(buffer));
  253.                 } catch (InvalidBlockException e) {
  254.                     uberblockList.add(null);
  255.                 } catch (BufferUnderflowException e) {
  256.                     buffer.position(LAST_UBERBLOCK);
  257.                 }
  258.             }
  259.  
  260.             uberblocks = uberblockList.toArray(new Uberblock[0]);
  261.         }
  262.        
  263.         public Uberblock[] getUberblocks() {
  264.             return uberblocks;
  265.         }
  266.        
  267.         public long getBase() {
  268.             return base;
  269.         }
  270.     }
  271.    
  272.     public static abstract class ZfsStruct {
  273.         protected BigInteger getUnsignedBigInteger(ByteBuffer buffer, int bytes) {
  274.             if (bytes < 1) {
  275.                 throw new IllegalArgumentException();
  276.             }
  277.            
  278.             // Pad the array with a leading 0x00 to ensure the result is positive
  279.             byte[] temp = new byte[bytes + 1];
  280.            
  281.             if (buffer.order() == ByteOrder.BIG_ENDIAN) {
  282.                 buffer.get(temp, 1, bytes);
  283.             } else {
  284.                 // Read the bytes, then flip the order
  285.                 buffer.get(temp, 0, bytes);
  286.                 for (int i = 0, j = temp.length - 1; i < temp.length / 2; i++, j--) {
  287.                     byte temp2 = temp[i];
  288.                     temp[i] = temp[j];
  289.                     temp[j] = temp2;
  290.                 }
  291.             }
  292.            
  293.             return new BigInteger(temp);
  294.         }
  295.     }
  296. }
Advertisement
Add Comment
Please, Sign In to add comment