tc_enter_chroot.py revision c7f1593f9af3ea1b9264b37628c36f3a70e1749a
1#!/usr/bin/python 2# 3# Copyright 2010 Google Inc. All Rights Reserved. 4 5"""Script to enter the ChromeOS chroot with mounted sources. 6 7This script enters the chroot with mounted sources. 8""" 9 10__author__ = "asharif@google.com (Ahmad Sharif)" 11 12import getpass 13import optparse 14import os 15import pwd 16import stat 17import sys 18 19from utils import command_executer 20from utils import logger 21from utils import misc 22 23 24class MountPoint: 25 def __init__(self, external_dir, mount_dir, owner, options=None): 26 self.external_dir = os.path.realpath(external_dir) 27 self.mount_dir = os.path.realpath(mount_dir) 28 self.owner = owner 29 self.options = options 30 31 32 def CreateAndOwnDir(self, dir_name): 33 retval = 0 34 if not os.path.exists(dir_name): 35 command = "mkdir -p " + dir_name 36 command += " || sudo mkdir -p " + dir_name 37 retval = command_executer.GetCommandExecuter().RunCommand(command) 38 if retval != 0: 39 return retval 40 pw = pwd.getpwnam(self.owner) 41 if os.stat(dir_name).st_uid != pw.pw_uid: 42 command = "sudo chown -f " + self.owner + " " + dir_name 43 retval = command_executer.GetCommandExecuter().RunCommand(command) 44 return retval 45 46 47 def DoMount(self): 48 ce = command_executer.GetCommandExecuter() 49 mount_signature = "%s on %s" % (self.external_dir, self.mount_dir) 50 command = "mount" 51 retval, out, err = ce.RunCommand(command, return_output=True) 52 if mount_signature not in out: 53 retval = self.CreateAndOwnDir(self.mount_dir) 54 logger.GetLogger().LogFatalIf(retval, "Cannot create mount_dir!") 55 retval = self.CreateAndOwnDir(self.external_dir) 56 logger.GetLogger().LogFatalIf(retval, "Cannot create external_dir!") 57 retval = self.MountDir() 58 logger.GetLogger().LogFatalIf(retval, "Cannot mount!") 59 return retval 60 else: 61 return 0 62 63 64 def UnMount(self): 65 ce = command_executer.GetCommandExecuter() 66 return ce.RunCommand("sudo umount %s" % self.mount_dir) 67 68 69 def MountDir(self): 70 command = "sudo mount --bind " + self.external_dir + " " + self.mount_dir 71 if self.options == "ro": 72 command += " && sudo mount --bind -oremount,ro " + self.mount_dir 73 retval = command_executer.GetCommandExecuter().RunCommand(command) 74 return retval 75 76 77 def __str__(self): 78 ret = "" 79 ret += self.external_dir + "\n" 80 ret += self.mount_dir + "\n" 81 if self.owner: 82 ret += self.owner + "\n" 83 if self.options: 84 ret += self.options + "\n" 85 return ret 86 87 88def Main(argv, return_output=False): 89 """The main function.""" 90 parser = optparse.OptionParser() 91 parser.add_option("-c", "--chromeos_root", dest="chromeos_root", 92 default="../..", 93 help="ChromeOS root checkout directory.") 94 parser.add_option("-t", "--toolchain_root", dest="toolchain_root", 95 help="Toolchain root directory.") 96 parser.add_option("-o", "--output", dest="output", 97 help="Toolchain output directory") 98 parser.add_option("--sudo", dest="sudo", 99 action="store_true", 100 default=False, 101 help="Run the command with sudo.") 102 parser.add_option("-r", "--third_party", dest="third_party", 103 help="The third_party directory to mount.") 104 parser.add_option("-m", "--other_mounts", dest="other_mounts", 105 help="Other mount points in the form: " + 106 "dir:mounted_dir:options") 107 parser.add_option("-s", "--mount-scripts-only", 108 dest="mount_scripts_only", 109 action="store_true", 110 default=False, 111 help="Mount only the scripts dir, and not the sources.") 112 113 passthrough_argv = [] 114 (options, passthrough_argv) = parser.parse_args(argv) 115 116 chromeos_root = options.chromeos_root 117 118 chromeos_root = os.path.expanduser(chromeos_root) 119 if options.toolchain_root: 120 options.toolchain_root = os.path.expanduser(options.toolchain_root) 121 122 chromeos_root = os.path.abspath(chromeos_root) 123 124 tc_dirs = [] 125 if options.toolchain_root is None or options.mount_scripts_only: 126 m = "toolchain_root not specified. Will not mount toolchain dirs." 127 logger.GetLogger().LogWarning(m) 128 else: 129 tc_dirs = [options.toolchain_root + "/google_vendor_src_branch/gcc", 130 options.toolchain_root + "/google_vendor_src_branch/binutils"] 131 132 for tc_dir in tc_dirs: 133 if not os.path.exists(tc_dir): 134 logger.GetLogger().LogError("toolchain path " + 135 tc_dir + " does not exist!") 136 parser.print_help() 137 sys.exit(1) 138 139 if not os.path.exists(chromeos_root): 140 logger.GetLogger().LogError("chromeos_root " + options.chromeos_root + 141 " does not exist!") 142 parser.print_help() 143 sys.exit(1) 144 145 if not os.path.exists(chromeos_root + "/src/scripts/build_packages"): 146 logger.GetLogger().LogError(options.chromeos_root + 147 "/src/scripts/build_packages" 148 " not found!") 149 parser.print_help() 150 sys.exit(1) 151 152 version_dir = os.path.realpath(os.path.expanduser(os.path.dirname(__file__))) 153 154 mounted_tc_root = "/usr/local/toolchain_root" 155 full_mounted_tc_root = chromeos_root + "/chroot/" + mounted_tc_root 156 full_mounted_tc_root = os.path.abspath(full_mounted_tc_root) 157 158 mount_points = [] 159 for tc_dir in tc_dirs: 160 last_dir = misc.GetRoot(tc_dir)[1] 161 mount_point = MountPoint(tc_dir, full_mounted_tc_root + "/" + last_dir, 162 getpass.getuser(), "ro") 163 mount_points.append(mount_point) 164 165 # Add the third_party mount point if it exists 166 if options.third_party: 167 third_party_dir = options.third_party 168 logger.GetLogger().LogFatalIf(not os.path.isdir(third_party_dir), 169 "--third_party option is not a valid dir.") 170 else: 171 third_party_dir = os.path.abspath("%s/../../../third_party" % 172 os.path.dirname(__file__)) 173 174 if os.path.isdir(third_party_dir): 175 mount_point = MountPoint(third_party_dir, 176 ("%s/%s" % 177 (full_mounted_tc_root, 178 os.path.basename(third_party_dir))), 179 getpass.getuser()) 180 mount_points.append(mount_point) 181 182 output = options.output 183 if output is None and options.toolchain_root: 184 # Mount the output directory at /usr/local/toolchain_root/output 185 output = options.toolchain_root + "/output" 186 187 if output: 188 mount_points.append(MountPoint(output, full_mounted_tc_root + "/output", 189 getpass.getuser())) 190 191 # Mount the other mount points 192 mount_points += CreateMountPointsFromString(options.other_mounts, 193 chromeos_root + "/chroot/") 194 195 last_dir = misc.GetRoot(version_dir)[1] 196 197 # Mount the version dir (v14) at /usr/local/toolchain_root/v14 198 mount_point = MountPoint(version_dir, full_mounted_tc_root + "/" + last_dir, 199 getpass.getuser()) 200 mount_points.append(mount_point) 201 202 for mount_point in mount_points: 203 retval = mount_point.DoMount() 204 if retval != 0: 205 return retval 206 207 # Finally, create the symlink to build-gcc. 208 command = "sudo chown " + getpass.getuser() + " " + full_mounted_tc_root 209 retval = command_executer.GetCommandExecuter().RunCommand(command) 210 211 try: 212 CreateSymlink(last_dir + "/build-gcc", full_mounted_tc_root + "/build-gcc") 213 CreateSymlink(last_dir + "/build-binutils", full_mounted_tc_root + "/build-binutils") 214 except Exception as e: 215 logger.GetLogger().LogError(str(e)) 216 217 # Now call cros_sdk --enter with the rest of the arguments. 218 command = "cd %s/src/scripts && cros_sdk --enter" % chromeos_root 219 220 if len(passthrough_argv) > 1: 221 inner_command = " ".join(passthrough_argv[1:]) 222 inner_command = inner_command.strip() 223 if inner_command.startswith("-- "): 224 inner_command = inner_command[3:] 225 command_file = "tc_enter_chroot.cmd" 226 command_file_path = chromeos_root + "/src/scripts/" + command_file 227 retval = command_executer.GetCommandExecuter().RunCommand("sudo rm -f " + command_file_path) 228 if retval != 0: 229 return retval 230 f = open(command_file_path, "w") 231 f.write(inner_command) 232 f.close() 233 logger.GetLogger().LogCmd(inner_command) 234 retval = command_executer.GetCommandExecuter().RunCommand("chmod +x " + command_file_path) 235 if retval != 0: 236 return retval 237 238 if options.sudo: 239 command += " sudo ./" + command_file 240 else: 241 command += " ./" + command_file 242 retval = command_executer.GetCommandExecuter().RunCommand(command, return_output) 243 return retval 244 else: 245 os.chdir("%s/src/scripts" % chromeos_root) 246 ce = command_executer.GetCommandExecuter() 247 [ret, out, err] = ce.RunCommand("which cros_sdk", return_output=True) 248 cros_sdk_binary = out.split()[0] 249 return os.execv(cros_sdk_binary, ["", "--enter"]) 250 251 252def CreateMountPointsFromString(mount_strings, chroot_dir): 253 # String has options in the form dir:mount:options 254 mount_points = [] 255 if not mount_strings: 256 return mount_points 257 mount_list = mount_strings.split() 258 for mount_string in mount_list: 259 mount_values = mount_string.split(":") 260 external_dir = mount_values[0] 261 mount_dir = mount_values[1] 262 if len(mount_values) > 2: 263 options = mount_values[2] 264 else: 265 options = None 266 mount_point = MountPoint(external_dir, chroot_dir + "/" + mount_dir, 267 getpass.getuser(), options) 268 mount_points.append(mount_point) 269 return mount_points 270 271 272def CreateSymlink(target, link_name): 273 logger.GetLogger().LogFatalIf(target.startswith("/"), 274 "Can't create symlink to absolute path!") 275 real_from_file = misc.GetRoot(link_name)[0] + "/" + target 276 if os.path.realpath(real_from_file) != os.path.realpath(link_name): 277 if os.path.exists(link_name): 278 command = "rm -rf " + link_name 279 command_executer.GetCommandExecuter().RunCommand(command) 280 os.symlink(target, link_name) 281 282 283if __name__ == "__main__": 284 retval = Main(sys.argv) 285 sys.exit(retval) 286