1# common python utility routines for the Bionic tool scripts
2
3import logging
4import os
5import string
6import sys
7
8
9def panic(msg):
10    sys.stderr.write(os.path.basename(sys.argv[0]) + ": error: ")
11    sys.stderr.write(msg)
12    sys.exit(1)
13
14
15def get_kernel_headers_dir():
16    return os.path.join(get_android_root(), "external/kernel-headers")
17
18
19def get_kernel_headers_original_dir():
20    return os.path.join(get_kernel_headers_dir(), "original")
21
22
23def get_kernel_headers_modified_dir():
24    return os.path.join(get_kernel_headers_dir(), "modified")
25
26
27def get_kernel_dir():
28    return os.path.join(get_android_root(), "bionic/libc/kernel")
29
30
31def get_android_root():
32    if "ANDROID_BUILD_TOP" in os.environ:
33        # Verify that the current directory is in the root.
34        # If not, then print an error.
35        cwd = os.getcwd()
36        root = os.environ["ANDROID_BUILD_TOP"]
37        if len(cwd) < len(root) or not root == cwd[:len(root)]:
38            panic("Not in android tree pointed at by ANDROID_BUILD_TOP (%s)\n" % root)
39        return os.environ["ANDROID_BUILD_TOP"]
40    panic("Unable to find root of tree, did you forget to lunch a target?\n")
41
42
43class StringOutput:
44    def __init__(self):
45        self.line = ""
46
47    def write(self,msg):
48        self.line += msg
49        logging.debug("write '%s'" % msg)
50
51    def get(self):
52        return self.line
53
54
55def create_file_path(path):
56    dirs = []
57    while 1:
58        parent = os.path.dirname(path)
59        #print "parent: %s <- %s" % (parent, path)
60        if parent == "/" or parent == "":
61            break
62        dirs.append(parent)
63        path = parent
64
65    dirs.reverse()
66    for dir in dirs:
67        #print "dir %s" % dir
68        if os.path.isdir(dir):
69            continue
70        os.mkdir(dir)
71
72
73class BatchFileUpdater:
74    """a class used to edit several files at once"""
75    def __init__(self):
76        self.old_files = set()
77        self.new_files = set()
78        self.new_data  = {}
79
80    def readFile(self,path):
81        #path = os.path.realpath(path)
82        if os.path.exists(path):
83            self.old_files.add(path)
84
85    def readDir(self,path):
86        #path = os.path.realpath(path)
87        for root, dirs, files in os.walk(path):
88            for f in files:
89                dst = "%s/%s" % (root,f)
90                self.old_files.add(dst)
91
92    def editFile(self,dst,data):
93        """edit a destination file. if the file is not mapped from a source,
94           it will be added. return 0 if the file content wasn't changed,
95           1 if it was edited, or 2 if the file is new"""
96        #dst = os.path.realpath(dst)
97        result = 1
98        if os.path.exists(dst):
99            f = open(dst, "r")
100            olddata = f.read()
101            f.close()
102            if olddata == data:
103                self.old_files.remove(dst)
104                return 0
105        else:
106            result = 2
107
108        self.new_data[dst] = data
109        self.new_files.add(dst)
110        return result
111
112    def getChanges(self):
113        """determine changes, returns (adds, deletes, edits)"""
114        adds    = set()
115        edits   = set()
116        deletes = set()
117
118        for dst in self.new_files:
119            if not (dst in self.old_files):
120                adds.add(dst)
121            else:
122                edits.add(dst)
123
124        for dst in self.old_files:
125            if not dst in self.new_files:
126                deletes.add(dst)
127
128        return (adds, deletes, edits)
129
130    def _writeFile(self,dst):
131        if not os.path.exists(os.path.dirname(dst)):
132            create_file_path(dst)
133        f = open(dst, "w")
134        f.write(self.new_data[dst])
135        f.close()
136
137    def updateFiles(self):
138        adds, deletes, edits = self.getChanges()
139
140        for dst in sorted(adds):
141            self._writeFile(dst)
142
143        for dst in sorted(edits):
144            self._writeFile(dst)
145
146        for dst in sorted(deletes):
147            os.remove(dst)
148