8 import mic.utils.fs_related as fs_related
9 import mic.utils.misc as misc
10 import mic.utils.errors as errors
12 def cleanup_after_chroot(targettype,imgmount,tmpdir,tmpmnt):
13 if imgmount and targettype == "img":
16 shutil.rmtree(tmpdir, ignore_errors = True)
18 shutil.rmtree(tmpmnt, ignore_errors = True)
20 def check_bind_mounts(chrootdir, bindmounts):
22 mounts = bindmounts.split(";")
26 srcdst = mount.split(":")
29 if not os.path.isdir(srcdst[0]):
31 if srcdst[1] == "" or srcdst[1] == "none":
33 if srcdst[0] in ("/proc", "/proc/sys/fs/binfmt_misc", "/", "/sys", "/dev", "/dev/pts", "/dev/shm", "/var/lib/dbus", "/var/run/dbus", "/var/lock"):
37 srcdst[1] = os.path.abspath(os.path.expanduser(srcdst[0]))
39 srcdst[1] = os.path.abspath(os.path.expanduser(srcdst[1]))
40 tmpdir = chrootdir + "/" + srcdst[1]
41 if os.path.isdir(tmpdir):
42 print "Warning: dir %s has existed." % tmpdir
45 def cleanup_mounts(chrootdir):
46 checkpoints = ["/proc/sys/fs/binfmt_misc", "/proc", "/sys", "/dev/pts", "/dev/shm", "/dev", "/var/lib/dbus", "/var/run/dbus", "/var/lock"]
47 dev_null = os.open("/dev/null", os.O_WRONLY)
48 umountcmd = misc.find_binary_path("umount")
49 for point in checkpoints:
51 args = [ umountcmd, "-l", chrootdir + point ]
52 subprocess.call(args, stdout=dev_null, stderr=dev_null)
53 catcmd = misc.find_binary_path("cat")
54 args = [ catcmd, "/proc/mounts" ]
55 proc_mounts = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=dev_null)
56 outputs = proc_mounts.communicate()[0].strip().split("\n")
58 if line.find(os.path.abspath(chrootdir)) >= 0:
59 if os.path.abspath(chrootdir) == line.split()[1]:
61 point = line.split()[1]
63 args = [ umountcmd, "-l", point ]
64 ret = subprocess.call(args, stdout=dev_null, stderr=dev_null)
66 print "ERROR: failed to unmount %s" % point
72 def setup_chrootenv(chrootdir, bindmounts = None):##move to mic/utils/misc
73 global chroot_lockfd, chroot_lock
74 def get_bind_mounts(chrootdir, bindmounts):
76 if bindmounts in ("", None):
78 mounts = bindmounts.split(";")
82 srcdst = mount.split(":")
83 srcdst[0] = os.path.abspath(os.path.expanduser(srcdst[0]))
86 if not os.path.isdir(srcdst[0]):
88 if srcdst[0] in ("/proc", "/proc/sys/fs/binfmt_misc", "/", "/sys", "/dev", "/dev/pts", "/dev/shm", "/var/lib/dbus", "/var/run/dbus", "/var/lock"):
89 pwarning("%s will be mounted by default." % srcdst[0])
91 if srcdst[1] == "" or srcdst[1] == "none":
94 srcdst[1] = os.path.abspath(os.path.expanduser(srcdst[1]))
95 if os.path.isdir(chrootdir + "/" + srcdst[1]):
96 pwarning("%s has existed in %s , skip it." % (srcdst[1], chrootdir))
98 chrootmounts.append(fs_related.BindChrootMount(srcdst[0], chrootdir, srcdst[1]))
100 """Default bind mounts"""
101 chrootmounts.append(fs_related.BindChrootMount("/proc", chrootdir, None))
102 chrootmounts.append(fs_related.BindChrootMount("/proc/sys/fs/binfmt_misc", chrootdir, None))
103 chrootmounts.append(fs_related.BindChrootMount("/sys", chrootdir, None))
104 chrootmounts.append(fs_related.BindChrootMount("/dev", chrootdir, None))
105 chrootmounts.append(fs_related.BindChrootMount("/dev/pts", chrootdir, None))
106 chrootmounts.append(fs_related.BindChrootMount("/dev/shm", chrootdir, None))
107 chrootmounts.append(fs_related.BindChrootMount("/var/lib/dbus", chrootdir, None))
108 chrootmounts.append(fs_related.BindChrootMount("/var/run/dbus", chrootdir, None))
109 chrootmounts.append(fs_related.BindChrootMount("/var/lock", chrootdir, None))
110 chrootmounts.append(fs_related.BindChrootMount("/", chrootdir, "/parentroot", "ro"))
111 for kernel in os.listdir("/lib/modules"):
112 chrootmounts.append(fs_related.BindChrootMount("/lib/modules/" + kernel, chrootdir, None, "ro"))
116 def bind_mount(chrootmounts):
117 for b in chrootmounts:
118 print "bind_mount: %s -> %s" % (b.src, b.dest)
121 def setup_resolv(chrootdir):
122 shutil.copyfile("/etc/resolv.conf", chrootdir + "/etc/resolv.conf")
124 globalmounts = get_bind_mounts(chrootdir, bindmounts)
125 bind_mount(globalmounts)
126 setup_resolv(chrootdir)
128 dstmtab = chrootdir + mtab
129 if not os.path.islink(dstmtab):
130 shutil.copyfile(mtab, dstmtab)
131 chroot_lock = os.path.join(chrootdir, ".chroot.lock")
132 chroot_lockfd = open(chroot_lock, "w")
135 def cleanup_chrootenv(chrootdir, bindmounts = None, globalmounts = []):
136 global chroot_lockfd, chroot_lock
137 def bind_unmount(chrootmounts):
138 chrootmounts.reverse()
139 for b in chrootmounts:
140 print "bind_unmount: %s -> %s" % (b.src, b.dest)
143 def cleanup_resolv(chrootdir):
144 fd = open(chrootdir + "/etc/resolv.conf", "w")
148 def kill_processes(chrootdir):
149 for file in glob.glob("/proc/*/root"):
151 if os.readlink(file) == chrootdir:
152 pid = int(file.split("/")[2])
157 def cleanup_mountdir(chrootdir, bindmounts):
158 if bindmounts == "" or bindmounts == None:
161 mounts = bindmounts.split(";")
165 srcdst = mount.split(":")
167 srcdst.append("none")
168 if srcdst[1] == "" or srcdst[1] == "none":
169 srcdst[1] = srcdst[0]
170 srcdst[1] = os.path.abspath(os.path.expanduser(srcdst[1]))
171 tmpdir = chrootdir + "/" + srcdst[1]
172 if os.path.isdir(tmpdir):
173 if len(os.listdir(tmpdir)) == 0:
174 shutil.rmtree(tmpdir, ignore_errors = True)
176 print "Warning: dir %s isn't empty." % tmpdir
178 chroot_lockfd.close()
179 bind_unmount(globalmounts)
180 if not fs_related.my_fuser(chroot_lock):
181 tmpdir = chrootdir + "/parentroot"
182 if len(os.listdir(tmpdir)) == 0:
183 shutil.rmtree(tmpdir, ignore_errors = True)
184 cleanup_resolv(chrootdir)
185 if os.path.exists(chrootdir + "/etc/mtab"):
186 os.unlink(chrootdir + "/etc/mtab")
187 kill_processes(chrootdir)
188 cleanup_mountdir(chrootdir, bindmounts)
190 def chroot(chrootdir, bindmounts = None, execute = "/bin/bash"):
195 dev_null = os.open("/dev/null", os.O_WRONLY)
196 files_to_check = ["/bin/bash", "/sbin/init"]
198 architecture_found = False
200 """ Register statically-linked qemu-arm if it is an ARM fs """
203 for ftc in files_to_check:
204 ftc = "%s/%s" % (chrootdir,ftc)
206 # Return code of 'file' is "almost always" 0 based on some man pages
207 # so we need to check the file existance first.
208 if not os.path.exists(ftc):
211 filecmd = misc.find_binary_path("file")
212 initp1 = subprocess.Popen([filecmd, ftc], stdout=subprocess.PIPE, stderr=dev_null)
213 fileOutput = initp1.communicate()[0].strip().split("\n")
215 for i in range(len(fileOutput)):
216 if fileOutput[i].find("ARM") > 0:
217 qemu_emulator = misc.setup_qemu_emulator(chrootdir, "arm")
218 architecture_found = True
220 if fileOutput[i].find("Intel") > 0:
221 architecture_found = True
224 if architecture_found:
228 if not architecture_found:
229 raise errors.CreatorError("Failed to get architecture from any of the following files %s from chroot." % files_to_check)
232 print "Launching shell. Exit to continue."
233 print "----------------------------------"
234 globalmounts = setup_chrootenv(chrootdir, bindmounts)
235 args = shlex.split(execute)
236 subprocess.call(args, preexec_fn = mychroot)
237 except OSError, (err, msg):
238 raise errors.CreatorError("Failed to chroot: %s" % msg)
240 cleanup_chrootenv(chrootdir, bindmounts, globalmounts)
242 os.unlink(chrootdir + qemu_emulator)