modularize
[mapsector.git] / lib / 50_scan_reiserfs.sh
1 detect_reiserfs()
2 {
3     which debugreiserfs >/dev/null 2>&1 && debugreiserfs $device >/dev/null 2>&1
4 }
5
6 describe_reiserfs()
7 {
8     echo "    reiserfs"
9 }
10
11 scan_reiserfs()
12 {
13     local blocksize
14     local block
15     local subsector
16
17     echo "fstype reiserfs"
18
19     # Step 6: Get filesystem blocksize and convert sector number to filesystem block number
20
21     blocksize="`debugreiserfs $device 2>/dev/null | awk '/^Blocksize:/{print $2/512}'`"
22     
23     if [ -z "$blocksize" ]; then
24         echo "! $device is not reiserfs" 1>&2
25         exit 1
26     fi
27
28     block="`dc -e "$sector $blocksize ~ n [ ] n p"`" #`"
29     subsector="${block% *}"
30     block="${block#* }"
31
32     echo "blocksize $blocksize"
33     echo "block $block"
34     echo "subsector $subsector"
35
36     # Step 7: Check, whether block is in use
37
38     if debugreiserfs -1 $block $device 2>&1 >/dev/null | grep -qF "free in ondisk bitmap"; then
39         echo "blockstate free"
40         exit 0
41     fi
42     echo "blockstate used"
43
44     # Use debugreiserfs -1 to check the block type. This however only works if the block is readable.
45     type="`debugreiserfs -1 $block $device 2>/dev/null | sed -e '/^=*$/d' | head -1`"
46
47     case "$type" in
48         "Looks like unformatted")  type="data"          ;;
49         "Reiserfs super block"*)   type="superblock"    ;;
50         "LEAF NODE"*)              type="meta"          ;;
51         "INTERNAL NODE"*)          type="meta"          ;;
52         "Desc block"*)             type="journal"       ;;
53         *)                         type=""              ;;
54     esac
55
56     if [ -n "$type" ]; then
57         echo "blocktype $type"
58     fi
59
60     # Step 8: Find object id to which this block belongs
61     # Step 9: Find file name(s) referencing this object id
62
63     # Currently we only look for $block in indirect blocks.
64
65     python - $device $block <<EOF
66 import sys
67 import os
68 import os.path
69
70 device = sys.argv[1]
71 blocknr = int(sys.argv[2])
72
73 dirtree = {}
74 blockid = None
75
76 fp = os.popen("debugreiserfs -d %s 2>/dev/null" % device)
77
78 def parse_leafnode():
79     global fp
80     l = fp.readline()
81     #sys.stderr.write("> leafnode(1): %s\n" % repr(l))
82     if not l.startswith("LEAF NODE") : return
83     for i in range(4) : fp.readline()
84     while True:
85         l = fp.readline()
86         #sys.stderr.write("> leafnode(2): %s\n" % repr(l))
87         parts = l.split("|")
88         if len(parts)<2 : return
89         parts = parts[2].split()
90         if len(parts)<4 : return
91         obid=(int(parts[0]),int(parts[1]))
92         if   parts[3] == "DIR" : parse_dir(obid)
93         elif parts[3] == "IND" : parse_indirect(obid)
94         else:
95             while True:
96                 l =  fp.readline().strip()
97                 #sys.stderr.write("> leafnode(3): %s\n" % repr(l))
98                 if l == 79*"-" or l == 67*"=" : break
99
100 def parse_dir(obid):
101     global fp
102     global dirtree
103     fp.readline()
104     while True:
105         try:
106             l = fp.readline().rstrip()
107             #sys.stderr.write("> dir: %s\n" % repr(l))
108             if l == 79*"-" or l == 67*"=": return
109             if l.endswith("not set"): continue
110             i = l.index("\"(")
111             name = l[6:6+int(l[i+2:i+5])]
112             if name == "." or name == ".." : continue
113             i = l.index("[",len(name)+12)
114             entryid = tuple(map(int,l[i+1:l.index("]",i+1)].split()))
115             entry = dirtree.get(entryid)
116             if entry is None : entry = dirtree[entryid] = set()
117             entry.add((name,obid))
118         except ValueError:
119             pass
120
121 def parse_indirect(obid):
122     global fp
123     global blocknr
124     global blockid
125     fp.readline()
126     for pointer in fp.readline().strip()[1:-1].split():
127         i = pointer.find("(")
128         if i == -1:
129             blkmin = blkmax = int(pointer)
130         else:
131             blkmin = int(pointer[:i])
132             blkmax = blkmin+int(pointer[i+1:-1])-1
133         if blocknr >= blkmin and blocknr <= blkmax:
134             blockid = obid
135     fp.readline()
136
137 def scan_path(id):
138     global dirtree
139     entry = dirtree.get(id)
140     #sys.stderr.write("> scan_path: %s->%s\n" % (id, entry))
141     if entry is None:
142         return [ '/' ]
143     else:
144         rv = []
145         for name, parent in entry:
146             for path in scan_path(parent):
147                 rv.append(os.path.join(path,name))
148         return rv
149
150 def parse():
151     global fp
152     while True:
153         while True:
154             l = fp.readline()
155             #sys.stderr.write("> parse: %s\n" % repr(l))
156             if not(l) : return
157             if l.strip() == 67*"=" : break
158         parse_leafnode()
159
160 parse()
161
162 if blockid is None:
163     sys.exit(0)
164
165 sys.stdout.write("objectid %d %d\n" % blockid)
166
167 for path in scan_path(blockid):
168     if path != '/':
169         sys.stdout.write("name %s\n" % path)
170 EOF
171
172 }
173
174 register_scanner "reiserfs"