#!/usr/bin/env python # Generate links in the root filesystem for appropriate packages. # This assumes that /bin and /sbin are symlinks to /usr/bin and /usr/sbin. packages = [ "awk", "bash", "busybox", # not that anything relies on it, but for fixing things "coreutils", "debianutils", "diffutils", "e2fsprogs", "ed", "file", "gawk", "grep", "gzip", "iproute2", "m4", "mawk", "mksh", "module-init-tools", "net-tools", "procps", "psmisc", "sed", "shadow", "sysvinit", "tar", "udev", "upstart", "util-linux", ] specials = { # Provided by glibc. # (ldconfig and sln are actually installed in /sbin by glibc.) "/usr/bin/catchsegv": None, "/usr/bin/gencat": None, "/usr/bin/getconf": None, "/usr/bin/getent": None, "/usr/bin/glibcbug": None, "/usr/bin/iconv": None, "/usr/bin/ldd": None, "/usr/bin/lddlibc4": None, "/usr/bin/locale": None, "/usr/bin/localedef": None, "/usr/bin/mtrace": None, "/usr/bin/memusage": None, "/usr/bin/memusagestat": None, "/usr/bin/pcprofiledump": None, "/usr/bin/rpcgen": None, "/usr/bin/sprof": None, "/usr/bin/tzselect": None, "/usr/bin/xtrace": None, "/usr/sbin/iconvconfig": None, "/usr/sbin/ldconfig": None, "/usr/sbin/nscd": None, "/usr/sbin/nscd_nischeck": None, "/usr/sbin/rpcinfo": None, "/usr/sbin/sln": None, "/usr/sbin/zdump": None, "/usr/sbin/zic": None, # An oddity -- this is the only binary still left in /lib on modern # Linux systems. (No good reason for that that I can see...) "/lib/cpp": "bin/cpp", "/usr/bin/cc": "bin/cc", "/usr/bin/cpp": "bin/cpp", "/usr/bin/gcc": "bin/gcc", "/usr/bin/ld": "bin/ld", "/usr/bin/expect": "bin/expect", "/usr/bin/runhaskell": "bin/runhaskell", "/usr/bin/python": "bin/python", "/usr/bin/perl": "bin/perl", "/usr/bin/tcl": "bin/tcl", "/usr/bin/tcl.real": "bin/tcl.real", "/usr/bin/tclsh": "bin/tclsh", "/usr/bin/wish": "bin/wish", "/usr/bin/wishx": "bin/wishx", "/usr/bin/wishx.real": "bin/wishx.real", "/usr/bin/sendmail": "bin/exim", "/usr/sbin/sendmail": "bin/exim", # ... and this is the only binary in /usr/lib: "/usr/lib/sendmail": "bin/exim", "/usr/bin/mail": "bin/mail", "/usr/bin/mailx": "bin/mailx", "/usr/sbin/fsck.jfs": "sbin/fsck.jfs", "/usr/sbin/fsck.reiser4": "sbin/fsck.reiser4", "/usr/sbin/fsck.xfs": "sbin/fsck.xfs", "/usr/sbin/mount.cifs": "sbin/mount.cifs", "/usr/sbin/umount.cifs": "sbin/umount.cifs", "/usr/sbin/mount.nfs": "sbin/mount.nfs", "/usr/sbin/umount.nfs": "sbin/umount.nfs", "/usr/sbin/mount.nfs4": "sbin/mount.nfs4", "/usr/sbin/umount.nfs4": "sbin/umount.nfs4", "/usr/sbin/mount.ntfs-3g": "sbin/mount.ntfs-3g", "/usr/sbin/umount.ntfs-3g": "sbin/umount.ntfs-3g", # Provided by linux. "/usr/include/asm": "include/asm", "/usr/include/asm-generic": "include/asm-generic", "/usr/include/linux": "include/linux", "/usr/include/mtd": "include/mtd", "/usr/include/rdma": "include/rdma", "/usr/include/sound": "include/sound", "/usr/include/video": "include/video", "/usr/share/icons": "share/icons", "/usr/share/mime": "share/mime", "/usr/share/themes": "share/themes", "/lib/udev": "lib/udev", } import sys, os, optparse from garstowlib.packages import * def ensure_symlink(src, dest, options): """Ensure that symlink dest exists, pointing to src.""" try: if os.readlink(in_root(dest)) == src: return except OSError: pass print " link " + in_root(dest) + " -> " + src if not options.dryrun: try: os.unlink(in_root(dest)) except OSError: pass os.symlink(src, in_root(dest)) def update_dir(src, dest, options): print "Updating " + dest pd = get_packages_dir() files = {} for p in packages: d = pd + "/" + p + "/" + src try: for f in os.listdir(in_root(d)): files[f] = d + "/" + f except OSError: pass to_remove = [] for f in os.listdir(in_root(dest)): df = dest + "/" + f if not (f in files or df in specials): to_remove.append(f) to_remove.sort() for f in to_remove: df = dest + "/" + f print " remove " + in_root(df) if not options.dryrun: os.unlink(in_root(df)) for (t, s) in files.items(): df = dest + "/" + t ensure_symlink(s, df, options) print def main(args): usage = "usage: %prog [options]" parser = optparse.OptionParser(usage=usage) parser.add_option("-n", action="store_true", dest="dryrun", help="show what will be done, rather than doing it") parser.add_option("--root", dest="root", metavar="DIR", help="specify root directory of system to operate on") options, args = parser.parse_args(args) if args != []: parser.error("no arguments necessary") if options.root is not None: set_root_dir(options.root) update_dir("bin", "/usr/bin", options) update_dir("sbin", "/usr/sbin", options) print "Making symlinks" sd = get_stow_dir() for (s, t) in specials.items(): if t is None: continue target = sd + "/" + t ensure_symlink(target, s, options) if __name__ == "__main__": main(sys.argv[1:])