1+ package cfig.lazybox
2+
3+ import org.slf4j.LoggerFactory
4+ import java.io.BufferedWriter
5+ import java.io.File
6+ import java.io.FileOutputStream
7+ import java.io.FileWriter
8+
9+ class MountAnalyzer {
10+ data class MountInfo (
11+ var dev : String = " " ,
12+ var mountPoint : String = " " ,
13+ var fsType : String = " " ,
14+ var flags : String? = null ,
15+ )
16+
17+ class MiComparator : Comparator <MountInfo > {
18+ override fun compare (p1 : MountInfo , p2 : MountInfo ): Int {
19+ var ret = p1.fsType.compareTo(p2.fsType) * 100
20+ ret + = p1.dev.compareTo(p2.dev) * 10
21+ ret + = p1.mountPoint.compareTo(p2.mountPoint) * 1
22+ return ret
23+ }
24+ }
25+
26+ fun run () {
27+ val loopApex = mutableListOf<MountInfo >()
28+ val dmApex = mutableListOf<MountInfo >()
29+ val tmpApex = mutableListOf<MountInfo >()
30+ val bootApex = mutableListOf<MountInfo >()
31+ val fuseInfo = mutableListOf<MountInfo >()
32+ val sysInfo = mutableListOf<MountInfo >()
33+ val androidRo = mutableListOf<MountInfo >()
34+ val androidRw = mutableListOf<MountInfo >()
35+ val otherRw = mutableListOf<MountInfo >()
36+ val unknownMi = mutableListOf<MountInfo >()
37+ val lines = File (" mount.log" ).readLines()
38+ lines.forEachIndexed { n, line ->
39+ val regex = Regex (" (\\ S+)\\ s+on\\ s+(\\ S+)\\ s+type\\ s+(\\ w+)\\ s+\\ (([^)]*)\\ )" ) // Capture flags
40+ val matchResult = regex.find(line)
41+ if (matchResult != null ) {
42+ val dev = matchResult.groupValues[1 ]
43+ val mountPoint = matchResult.groupValues[2 ]
44+ val fsType = matchResult.groupValues[3 ]
45+ val flags =
46+ if (matchResult.groupValues.size > 4 ) matchResult.groupValues[4 ] else null // Handle no flags
47+ val mi = MountInfo (dev, mountPoint, fsType, flags)
48+ if (mi.mountPoint.startsWith(" /apex" ) || mi.mountPoint.startsWith(" /bootstrap-apex" )) {
49+ if (mi.mountPoint.startsWith(" /bootstrap-apex" )) {
50+ bootApex.add(mi)
51+ } else if (mi.dev.startsWith(" /dev/block/loop" )) {
52+ loopApex.add(mi)
53+ } else if (mi.dev.startsWith(" /dev/block/dm" )) {
54+ dmApex.add(mi)
55+ } else if (mi.dev.startsWith(" tmpfs" )) {
56+ tmpApex.add(mi)
57+ } else {
58+ log.info(" $fsType : $dev -> $mountPoint " )
59+ throw IllegalStateException (" X1" )
60+ }
61+ } else if (mi.mountPoint.startsWith(" /sys/" ) || mi.mountPoint == " /sys" ) {
62+ sysInfo.add(mi)
63+ } else if (mi.fsType == " fuse" ) {
64+ fuseInfo.add(mi)
65+ } else {
66+ log.info(" $fsType : $dev -> $mountPoint " )
67+ if (mi.flags!! .contains(" ro," ) or mi.flags!! .contains(" ro)" )) {
68+ androidRo.add(mi)
69+ } else if (mi.flags!! .contains(" rw," ) or mi.flags!! .contains(" rw)" )) {
70+ if (mi.dev.startsWith(" /dev/" )) {
71+ androidRw.add(mi)
72+ } else {
73+ otherRw.add(mi)
74+ }
75+ } else {
76+ throw IllegalStateException (" X2" )
77+ }
78+ }
79+ } else { // For lines without flags
80+ val regexNoFlags = Regex (" (\\ S+)\\ s+on\\ s+(\\ S+)\\ s+type\\ s+(\\ w+)" )
81+ val matchResultNoFlags = regexNoFlags.find(line)
82+ if (matchResultNoFlags != null ) {
83+ val dev = matchResultNoFlags.groupValues[1 ]
84+ val mountPoint = matchResultNoFlags.groupValues[2 ]
85+ val fsType = matchResultNoFlags.groupValues[3 ]
86+ val mi = MountInfo (dev, mountPoint, fsType, null )
87+ unknownMi.add(mi)
88+ } else {
89+ throw IllegalStateException (" X3" )
90+ }
91+ }
92+ } // end-of-lines
93+ // sanity check, make sure consistent
94+ check(
95+ listOf (
96+ loopApex,
97+ dmApex,
98+ tmpApex,
99+ bootApex,
100+ fuseInfo,
101+ sysInfo,
102+ androidRo,
103+ androidRw,
104+ otherRw,
105+ unknownMi
106+ ).sumOf { it.size } == lines.size)
107+ // dump
108+ val infoNames = listOf (
109+ " fusefs" ,
110+ " sysfs" ,
111+ " Android RO" ,
112+ " Android RW" ,
113+ " other Rw" ,
114+ " loop apex" ,
115+ " dm apex" ,
116+ " tmp apex" ,
117+ " boot apex" ,
118+ " unknown"
119+ )
120+ BufferedWriter (FileWriter (File (" sorted_mount.log" ))).use { fos ->
121+ listOf (
122+ fuseInfo,
123+ sysInfo,
124+ androidRo,
125+ androidRw,
126+ otherRw,
127+ loopApex,
128+ dmApex,
129+ tmpApex,
130+ bootApex,
131+ unknownMi
132+ ).forEachIndexed { n, mis ->
133+ mis.sortWith(MiComparator ())
134+ log.info(infoNames.get(n))
135+ fos.write(infoNames.get(n) + " \n " )
136+ mis.forEachIndexed { index, it ->
137+ log.info(" [$index ] ${it.fsType} : ${it.dev} -> ${it.mountPoint} (${it.flags} )" )
138+ fos.write(" #$index | ${it.fsType} | ${it.dev} | ${it.mountPoint} | (${it.flags} )\n " )
139+ }
140+ fos.write(" \n " )
141+ }
142+ }
143+ }
144+
145+ companion object {
146+ private val log = LoggerFactory .getLogger(MountAnalyzer ::class .java)
147+ }
148+ }
0 commit comments