1*760c253cSXin Li#!/usr/bin/env python3 2*760c253cSXin Li# -*- coding: utf-8 -*- 3*760c253cSXin Li# Copyright 2010 The ChromiumOS Authors 4*760c253cSXin Li# Use of this source code is governed by a BSD-style license that can be 5*760c253cSXin Li# found in the LICENSE file. 6*760c253cSXin Li 7*760c253cSXin Li"""Script to enter the ChromeOS chroot with mounted sources. 8*760c253cSXin Li 9*760c253cSXin LiThis script enters the chroot with mounted sources. 10*760c253cSXin Li""" 11*760c253cSXin Li 12*760c253cSXin Li 13*760c253cSXin Li__author__ = "[email protected] (Ahmad Sharif)" 14*760c253cSXin Li 15*760c253cSXin Liimport argparse 16*760c253cSXin Liimport getpass 17*760c253cSXin Liimport os 18*760c253cSXin Liimport pwd 19*760c253cSXin Liimport sys 20*760c253cSXin Li 21*760c253cSXin Lifrom cros_utils import command_executer 22*760c253cSXin Lifrom cros_utils import logger 23*760c253cSXin Lifrom cros_utils import misc 24*760c253cSXin Li 25*760c253cSXin Li 26*760c253cSXin Liclass MountPoint(object): 27*760c253cSXin Li """Mount point class""" 28*760c253cSXin Li 29*760c253cSXin Li def __init__(self, external_dir, mount_dir, owner, options=None): 30*760c253cSXin Li self.external_dir = os.path.realpath(external_dir) 31*760c253cSXin Li self.mount_dir = os.path.realpath(mount_dir) 32*760c253cSXin Li self.owner = owner 33*760c253cSXin Li self.options = options 34*760c253cSXin Li 35*760c253cSXin Li def CreateAndOwnDir(self, dir_name): 36*760c253cSXin Li retv = 0 37*760c253cSXin Li if not os.path.exists(dir_name): 38*760c253cSXin Li command = "mkdir -p " + dir_name 39*760c253cSXin Li command += " || sudo mkdir -p " + dir_name 40*760c253cSXin Li retv = command_executer.GetCommandExecuter().RunCommand(command) 41*760c253cSXin Li if retv != 0: 42*760c253cSXin Li return retv 43*760c253cSXin Li pw = pwd.getpwnam(self.owner) 44*760c253cSXin Li if os.stat(dir_name).st_uid != pw.pw_uid: 45*760c253cSXin Li command = "sudo chown -f " + self.owner + " " + dir_name 46*760c253cSXin Li retv = command_executer.GetCommandExecuter().RunCommand(command) 47*760c253cSXin Li return retv 48*760c253cSXin Li 49*760c253cSXin Li def DoMount(self): 50*760c253cSXin Li ce = command_executer.GetCommandExecuter() 51*760c253cSXin Li mount_signature = "%s on %s" % (self.external_dir, self.mount_dir) 52*760c253cSXin Li command = "mount" 53*760c253cSXin Li retv, out, _ = ce.RunCommandWOutput(command) 54*760c253cSXin Li if mount_signature not in out: 55*760c253cSXin Li retv = self.CreateAndOwnDir(self.mount_dir) 56*760c253cSXin Li logger.GetLogger().LogFatalIf(retv, "Cannot create mount_dir!") 57*760c253cSXin Li retv = self.CreateAndOwnDir(self.external_dir) 58*760c253cSXin Li logger.GetLogger().LogFatalIf(retv, "Cannot create external_dir!") 59*760c253cSXin Li retv = self.MountDir() 60*760c253cSXin Li logger.GetLogger().LogFatalIf(retv, "Cannot mount!") 61*760c253cSXin Li return retv 62*760c253cSXin Li else: 63*760c253cSXin Li return 0 64*760c253cSXin Li 65*760c253cSXin Li def UnMount(self): 66*760c253cSXin Li ce = command_executer.GetCommandExecuter() 67*760c253cSXin Li return ce.RunCommand("sudo umount %s" % self.mount_dir) 68*760c253cSXin Li 69*760c253cSXin Li def MountDir(self): 70*760c253cSXin Li command = ( 71*760c253cSXin Li "sudo mount --bind " + self.external_dir + " " + self.mount_dir 72*760c253cSXin Li ) 73*760c253cSXin Li if self.options == "ro": 74*760c253cSXin Li command += " && sudo mount --bind -oremount,ro " + self.mount_dir 75*760c253cSXin Li retv = command_executer.GetCommandExecuter().RunCommand(command) 76*760c253cSXin Li return retv 77*760c253cSXin Li 78*760c253cSXin Li def __str__(self): 79*760c253cSXin Li ret = "" 80*760c253cSXin Li ret += self.external_dir + "\n" 81*760c253cSXin Li ret += self.mount_dir + "\n" 82*760c253cSXin Li if self.owner: 83*760c253cSXin Li ret += self.owner + "\n" 84*760c253cSXin Li if self.options: 85*760c253cSXin Li ret += self.options + "\n" 86*760c253cSXin Li return ret 87*760c253cSXin Li 88*760c253cSXin Li 89*760c253cSXin Lidef Main(argv, return_output=False): 90*760c253cSXin Li """The main function.""" 91*760c253cSXin Li 92*760c253cSXin Li parser = argparse.ArgumentParser() 93*760c253cSXin Li parser.add_argument( 94*760c253cSXin Li "-c", 95*760c253cSXin Li "--chromeos_root", 96*760c253cSXin Li dest="chromeos_root", 97*760c253cSXin Li default="../..", 98*760c253cSXin Li help="ChromeOS root checkout directory.", 99*760c253cSXin Li ) 100*760c253cSXin Li parser.add_argument( 101*760c253cSXin Li "-t", 102*760c253cSXin Li "--toolchain_root", 103*760c253cSXin Li dest="toolchain_root", 104*760c253cSXin Li help="Toolchain root directory.", 105*760c253cSXin Li ) 106*760c253cSXin Li parser.add_argument( 107*760c253cSXin Li "-o", "--output", dest="output", help="Toolchain output directory" 108*760c253cSXin Li ) 109*760c253cSXin Li parser.add_argument( 110*760c253cSXin Li "--sudo", 111*760c253cSXin Li dest="sudo", 112*760c253cSXin Li action="store_true", 113*760c253cSXin Li default=False, 114*760c253cSXin Li help="Run the command with sudo.", 115*760c253cSXin Li ) 116*760c253cSXin Li parser.add_argument( 117*760c253cSXin Li "-r", 118*760c253cSXin Li "--third_party", 119*760c253cSXin Li dest="third_party", 120*760c253cSXin Li help="The third_party directory to mount.", 121*760c253cSXin Li ) 122*760c253cSXin Li parser.add_argument( 123*760c253cSXin Li "-m", 124*760c253cSXin Li "--other_mounts", 125*760c253cSXin Li dest="other_mounts", 126*760c253cSXin Li help="Other mount points in the form: " "dir:mounted_dir:options", 127*760c253cSXin Li ) 128*760c253cSXin Li parser.add_argument( 129*760c253cSXin Li "-s", 130*760c253cSXin Li "--mount-scripts-only", 131*760c253cSXin Li dest="mount_scripts_only", 132*760c253cSXin Li action="store_true", 133*760c253cSXin Li default=False, 134*760c253cSXin Li help="Mount only the scripts dir, and not the sources.", 135*760c253cSXin Li ) 136*760c253cSXin Li parser.add_argument( 137*760c253cSXin Li "passthrough_argv", 138*760c253cSXin Li nargs="*", 139*760c253cSXin Li help="Command to be executed inside the chroot.", 140*760c253cSXin Li ) 141*760c253cSXin Li 142*760c253cSXin Li options = parser.parse_args(argv) 143*760c253cSXin Li 144*760c253cSXin Li chromeos_root = options.chromeos_root 145*760c253cSXin Li 146*760c253cSXin Li chromeos_root = os.path.expanduser(chromeos_root) 147*760c253cSXin Li if options.toolchain_root: 148*760c253cSXin Li options.toolchain_root = os.path.expanduser(options.toolchain_root) 149*760c253cSXin Li 150*760c253cSXin Li chromeos_root = os.path.abspath(chromeos_root) 151*760c253cSXin Li 152*760c253cSXin Li tc_dirs = [] 153*760c253cSXin Li if options.toolchain_root is None or options.mount_scripts_only: 154*760c253cSXin Li m = "toolchain_root not specified. Will not mount toolchain dirs." 155*760c253cSXin Li logger.GetLogger().LogWarning(m) 156*760c253cSXin Li else: 157*760c253cSXin Li tc_dirs = [ 158*760c253cSXin Li options.toolchain_root + "/google_vendor_src_branch/gcc", 159*760c253cSXin Li options.toolchain_root + "/google_vendor_src_branch/binutils", 160*760c253cSXin Li ] 161*760c253cSXin Li 162*760c253cSXin Li for tc_dir in tc_dirs: 163*760c253cSXin Li if not os.path.exists(tc_dir): 164*760c253cSXin Li logger.GetLogger().LogError( 165*760c253cSXin Li "toolchain path " + tc_dir + " does not exist!" 166*760c253cSXin Li ) 167*760c253cSXin Li parser.print_help() 168*760c253cSXin Li sys.exit(1) 169*760c253cSXin Li 170*760c253cSXin Li if not os.path.exists(chromeos_root): 171*760c253cSXin Li logger.GetLogger().LogError( 172*760c253cSXin Li "chromeos_root " + options.chromeos_root + " does not exist!" 173*760c253cSXin Li ) 174*760c253cSXin Li parser.print_help() 175*760c253cSXin Li sys.exit(1) 176*760c253cSXin Li 177*760c253cSXin Li if not os.path.exists(chromeos_root + "/src/scripts/build_packages"): 178*760c253cSXin Li logger.GetLogger().LogError( 179*760c253cSXin Li options.chromeos_root + "/src/scripts/build_packages" " not found!" 180*760c253cSXin Li ) 181*760c253cSXin Li parser.print_help() 182*760c253cSXin Li sys.exit(1) 183*760c253cSXin Li 184*760c253cSXin Li version_dir = os.path.realpath( 185*760c253cSXin Li os.path.expanduser(os.path.dirname(__file__)) 186*760c253cSXin Li ) 187*760c253cSXin Li 188*760c253cSXin Li mounted_tc_root = "/usr/local/toolchain_root" 189*760c253cSXin Li full_mounted_tc_root = chromeos_root + "/chroot/" + mounted_tc_root 190*760c253cSXin Li full_mounted_tc_root = os.path.abspath(full_mounted_tc_root) 191*760c253cSXin Li 192*760c253cSXin Li mount_points = [] 193*760c253cSXin Li for tc_dir in tc_dirs: 194*760c253cSXin Li last_dir = misc.GetRoot(tc_dir)[1] 195*760c253cSXin Li mount_point = MountPoint( 196*760c253cSXin Li tc_dir, 197*760c253cSXin Li full_mounted_tc_root + "/" + last_dir, 198*760c253cSXin Li getpass.getuser(), 199*760c253cSXin Li "ro", 200*760c253cSXin Li ) 201*760c253cSXin Li mount_points.append(mount_point) 202*760c253cSXin Li 203*760c253cSXin Li # Add the third_party mount point if it exists 204*760c253cSXin Li if options.third_party: 205*760c253cSXin Li third_party_dir = options.third_party 206*760c253cSXin Li logger.GetLogger().LogFatalIf( 207*760c253cSXin Li not os.path.isdir(third_party_dir), 208*760c253cSXin Li "--third_party option is not a valid dir.", 209*760c253cSXin Li ) 210*760c253cSXin Li else: 211*760c253cSXin Li third_party_dir = os.path.abspath( 212*760c253cSXin Li "%s/../../../third_party" % os.path.dirname(__file__) 213*760c253cSXin Li ) 214*760c253cSXin Li 215*760c253cSXin Li if os.path.isdir(third_party_dir): 216*760c253cSXin Li mount_point = MountPoint( 217*760c253cSXin Li third_party_dir, 218*760c253cSXin Li ( 219*760c253cSXin Li "%s/%s" 220*760c253cSXin Li % (full_mounted_tc_root, os.path.basename(third_party_dir)) 221*760c253cSXin Li ), 222*760c253cSXin Li getpass.getuser(), 223*760c253cSXin Li ) 224*760c253cSXin Li mount_points.append(mount_point) 225*760c253cSXin Li 226*760c253cSXin Li output = options.output 227*760c253cSXin Li if output is None and options.toolchain_root: 228*760c253cSXin Li # Mount the output directory at /usr/local/toolchain_root/output 229*760c253cSXin Li output = options.toolchain_root + "/output" 230*760c253cSXin Li 231*760c253cSXin Li if output: 232*760c253cSXin Li mount_points.append( 233*760c253cSXin Li MountPoint( 234*760c253cSXin Li output, full_mounted_tc_root + "/output", getpass.getuser() 235*760c253cSXin Li ) 236*760c253cSXin Li ) 237*760c253cSXin Li 238*760c253cSXin Li # Mount the other mount points 239*760c253cSXin Li mount_points += CreateMountPointsFromString( 240*760c253cSXin Li options.other_mounts, chromeos_root + "/chroot/" 241*760c253cSXin Li ) 242*760c253cSXin Li 243*760c253cSXin Li last_dir = misc.GetRoot(version_dir)[1] 244*760c253cSXin Li 245*760c253cSXin Li # Mount the version dir (v14) at /usr/local/toolchain_root/v14 246*760c253cSXin Li mount_point = MountPoint( 247*760c253cSXin Li version_dir, full_mounted_tc_root + "/" + last_dir, getpass.getuser() 248*760c253cSXin Li ) 249*760c253cSXin Li mount_points.append(mount_point) 250*760c253cSXin Li 251*760c253cSXin Li for mount_point in mount_points: 252*760c253cSXin Li retv = mount_point.DoMount() 253*760c253cSXin Li if retv != 0: 254*760c253cSXin Li return retv 255*760c253cSXin Li 256*760c253cSXin Li # Finally, create the symlink to build-gcc. 257*760c253cSXin Li command = "sudo chown " + getpass.getuser() + " " + full_mounted_tc_root 258*760c253cSXin Li retv = command_executer.GetCommandExecuter().RunCommand(command) 259*760c253cSXin Li 260*760c253cSXin Li try: 261*760c253cSXin Li CreateSymlink( 262*760c253cSXin Li last_dir + "/build-gcc", full_mounted_tc_root + "/build-gcc" 263*760c253cSXin Li ) 264*760c253cSXin Li CreateSymlink( 265*760c253cSXin Li last_dir + "/build-binutils", 266*760c253cSXin Li full_mounted_tc_root + "/build-binutils", 267*760c253cSXin Li ) 268*760c253cSXin Li except Exception as e: 269*760c253cSXin Li logger.GetLogger().LogError(str(e)) 270*760c253cSXin Li 271*760c253cSXin Li # Now call cros_sdk --enter with the rest of the arguments. 272*760c253cSXin Li command = "cd %s/src/scripts && cros_sdk --enter" % chromeos_root 273*760c253cSXin Li 274*760c253cSXin Li if len(options.passthrough_argv) > 1: 275*760c253cSXin Li inner_command = " ".join(options.passthrough_argv[1:]) 276*760c253cSXin Li inner_command = inner_command.strip() 277*760c253cSXin Li if inner_command.startswith("-- "): 278*760c253cSXin Li inner_command = inner_command[3:] 279*760c253cSXin Li command_file = "tc_enter_chroot.cmd" 280*760c253cSXin Li command_file_path = chromeos_root + "/src/scripts/" + command_file 281*760c253cSXin Li retv = command_executer.GetCommandExecuter().RunCommand( 282*760c253cSXin Li "sudo rm -f " + command_file_path 283*760c253cSXin Li ) 284*760c253cSXin Li if retv != 0: 285*760c253cSXin Li return retv 286*760c253cSXin Li with open(command_file_path, "w", encoding="utf-8") as f: 287*760c253cSXin Li f.write(inner_command) 288*760c253cSXin Li logger.GetLogger().LogCmd(inner_command) 289*760c253cSXin Li retv = command_executer.GetCommandExecuter().RunCommand( 290*760c253cSXin Li "chmod +x " + command_file_path 291*760c253cSXin Li ) 292*760c253cSXin Li if retv != 0: 293*760c253cSXin Li return retv 294*760c253cSXin Li 295*760c253cSXin Li if options.sudo: 296*760c253cSXin Li command += " sudo ./" + command_file 297*760c253cSXin Li else: 298*760c253cSXin Li command += " ./" + command_file 299*760c253cSXin Li retv = command_executer.GetCommandExecuter().RunCommandGeneric( 300*760c253cSXin Li command, return_output 301*760c253cSXin Li ) 302*760c253cSXin Li return retv 303*760c253cSXin Li else: 304*760c253cSXin Li os.chdir("%s/src/scripts" % chromeos_root) 305*760c253cSXin Li ce = command_executer.GetCommandExecuter() 306*760c253cSXin Li _, out, _ = ce.RunCommandWOutput("which cros_sdk") 307*760c253cSXin Li cros_sdk_binary = out.split()[0] 308*760c253cSXin Li return os.execv(cros_sdk_binary, ["", "--enter"]) 309*760c253cSXin Li 310*760c253cSXin Li 311*760c253cSXin Lidef CreateMountPointsFromString(mount_strings, chroot_dir): 312*760c253cSXin Li # String has options in the form dir:mount:options 313*760c253cSXin Li mount_points = [] 314*760c253cSXin Li if not mount_strings: 315*760c253cSXin Li return mount_points 316*760c253cSXin Li mount_list = mount_strings.split() 317*760c253cSXin Li for mount_string in mount_list: 318*760c253cSXin Li mount_values = mount_string.split(":") 319*760c253cSXin Li external_dir = mount_values[0] 320*760c253cSXin Li mount_dir = mount_values[1] 321*760c253cSXin Li if len(mount_values) > 2: 322*760c253cSXin Li options = mount_values[2] 323*760c253cSXin Li else: 324*760c253cSXin Li options = None 325*760c253cSXin Li mount_point = MountPoint( 326*760c253cSXin Li external_dir, 327*760c253cSXin Li chroot_dir + "/" + mount_dir, 328*760c253cSXin Li getpass.getuser(), 329*760c253cSXin Li options, 330*760c253cSXin Li ) 331*760c253cSXin Li mount_points.append(mount_point) 332*760c253cSXin Li return mount_points 333*760c253cSXin Li 334*760c253cSXin Li 335*760c253cSXin Lidef CreateSymlink(target, link_name): 336*760c253cSXin Li logger.GetLogger().LogFatalIf( 337*760c253cSXin Li target.startswith("/"), "Can't create symlink to absolute path!" 338*760c253cSXin Li ) 339*760c253cSXin Li real_from_file = misc.GetRoot(link_name)[0] + "/" + target 340*760c253cSXin Li if os.path.realpath(real_from_file) != os.path.realpath(link_name): 341*760c253cSXin Li if os.path.exists(link_name): 342*760c253cSXin Li command = "rm -rf " + link_name 343*760c253cSXin Li command_executer.GetCommandExecuter().RunCommand(command) 344*760c253cSXin Li os.symlink(target, link_name) 345*760c253cSXin Li 346*760c253cSXin Li 347*760c253cSXin Liif __name__ == "__main__": 348*760c253cSXin Li retval = Main(sys.argv) 349*760c253cSXin Li sys.exit(retval) 350