Wednesday 27 July 2016

Linux TAR restore files from tape unknown number of files, file size, block size and block number SOLVED

Recently I had one simple but time consuming request with lack of informatio from people that request came from! Do you have a feeling that it's always too little information when you need to do something for someone else?

Linux TAR restore files from tape unknown number of files, file size, block size and block number


And request was.....(wait for it...) to restore files from old LTO2 tapes. There were no information what so ever of how many files are there on tape or any information that could help me to quickly restore those archive to local file system. Only thing I knew it that archiving was made by using old backup software that we don't have anymore and not tar command. Ok, I know what you can say "Why don't you just restore one by one file?" Well, I start restore by doing exactly that - restoring one by one file but ... it start it turns out that there are many files from 5 to 10MB in size on 200GB LTO2 size tape.

How to restore archive from tape that you don't know anything? Well, I used dd command. So, it's easy. dd command require(or doesn't) two parameters: block size and block count. 

dd if=/dev/tape_device of=restored_file bs=block_size count=block_count

Because dd command is stupid and she only does what you tell her to do. She will copy block by block from input file(if) to output file(of) from memory pointer where he is now with block size(bs) and will copy that many block that you have defined in count. 

How to get bs and count from unknown tape? Use mt command and math!  By using mt command with status option you will get block number. Rewinding tape back and forward at begin and end of file, you can get block count of that file.
Here is example for first file on tape:

rewind tape on the beginning 
#mt -f /dev/IBMtape0n rewind
#mt -f /dev/IBMtape0n status
SCSI 2 tape drive:
File number=-1, block number=1, partition=0.
Tape block size 0 bytes. Density code 0x44 (no translation).
Soft error count since last status=0
General status bits on (1000000):
 ONLINE
 
#:mt -f /dev/IBMtape0n asf 1
Rewind at the beginning of second file. Remember that first file have position 0, second position 1, etc.
#mt -f /dev/IBMtape0n status
SCSI 2 tape drive:
File number=-1, block number=23442, partition=0.
Tape block size 0 bytes. Density code 0x44 (no translation).
Soft error count since last status=0
General status bits on (1000000):
 ONLINE

By subtracting block number from second beginning of second file and beginning of first file, you can get block count of first file. 
Ok, we have block count! What about block size? As Harry Callahan would say "Do you feel lucky?". I used 64k block size and it worked for me.

Ok, so you can now return one file at the time! But an this go faster? Hell, yea! Ok, I will explain this line by line


#!/bin/bash
for i in {0..100};
#for loop for 100 files on tape. There can be more or can be less,it's up to your tape
do 
echo
echo $i
echo xxxxxxxxxxxxxxxxxxx 
mt -f /dev/IBMtape0n asf $i
#rewind tape at beginning of $i 
a=`mt -f /dev/IBMtape0n status |grep number|awk '{print $4}'|awk -F',' '{print $1}'|awk -F'=' '{print $2}'`
# variable a is block number from begining of $i file
date
echo $a
mt -f /dev/IBMtape0n asf $((i+1)) 
#rewind tape at the beginning of next file($i+1)
b=`mt -f /dev/IBMtape0n status |grep number|awk '{print $4}'|awk -F',' '{print $1}'|awk -F'=' '{print $2}'`
# variable b is block number from begining of $i+1 file
echo $b
date
c=`echo "$b-$a"|bc`
#variable c is block count of file $i
echo $c
mt -f /dev/IBMtape0n asf $i
#rewind tape on beginning of file $i
echo "Start restore. File size is " 
echo "$c*64/1024"|bc
dd if=/dev/IBMtape0n of=backup_$i bs=64k count=$c
#start restore
echo Restore is
echo xxxxxxxxxxxxxxxxxxx
echo
done

I hope that this will save you time!