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