[tor-commits] [torbrowser/master] [2312 Linux] Remove shared-library symlinks from Lib/ and Lib/libz

erinn at torproject.org erinn at torproject.org
Sun Oct 23 23:18:31 UTC 2011


commit 77989a6a3f8ffb1e2acbbe7e79205fb964b8c8fb
Author: Robert Ransom <rransom.8774 at gmail.com>
Date:   Thu Sep 1 11:06:14 2011 -0400

    [2312 Linux] Remove shared-library symlinks from Lib/ and Lib/libz
---
 build-scripts/linux.mk                   |    7 +-
 build-scripts/remove-shared-lib-symlinks |  216 ++++++++++++++++++++++++++++++
 2 files changed, 222 insertions(+), 1 deletions(-)

diff --git a/build-scripts/linux.mk b/build-scripts/linux.mk
index 507f27c..4b83c8f 100644
--- a/build-scripts/linux.mk
+++ b/build-scripts/linux.mk
@@ -256,7 +256,8 @@ generic-bundle: directory-structure \
 		install-pidgin \
 		configure-apps \
 		launcher \
-		strip-it-stripper
+		strip-it-stripper \
+		remove-bundle-shared-lib-symlinks
 	touch generic-bundle.stamp
 
 APPDIR=$(DEST)/App
@@ -363,6 +364,10 @@ strip-it-stripper:
 	strip $(LIBSDIR)/*.so*
 	strip $(LIBSDIR)/libz/*.so*
 
+remove-bundle-shared-lib-symlinks:
+	./remove-shared-lib-symlinks $(LIBSDIR)
+	./remove-shared-lib-symlinks $(LIBSDIR)/libz
+
 ##
 ## How to create required extensions
 ##
diff --git a/build-scripts/remove-shared-lib-symlinks b/build-scripts/remove-shared-lib-symlinks
new file mode 100755
index 0000000..39d5060
--- /dev/null
+++ b/build-scripts/remove-shared-lib-symlinks
@@ -0,0 +1,216 @@
+#!/usr/bin/tclsh8.5
+
+set usage [string trimleft {
+usage: remove-shared-lib-symlinks $LIBSDIR
+
+Remove all shared library symlinks from the libraries in $LIBSDIR,
+renaming the libraries themselves so that the Linux dynamic loader
+will still load executables linked to those libraries properly.
+
+This program assumes that the contents of $LIBSDIR do not change while
+it is running.
+}]
+
+#* Return $x.  (The command [return $x] returns $x <em>from the
+# containing function</em>.)
+proc result {x} {
+    return $x
+}
+
+# Check that we have exactly one command-line argument.  If our
+# command line isn't what we expect, print a usage message to stderr
+# and die.
+#
+# As a special case, if our one command-line argument is "--help" or
+# "-help", print the usage message to stdout and exit.
+if {$argc != 1 ||
+    [lindex $argv 0] eq "--help" ||
+    [lindex $argv 0] eq "-help" ||
+    ![file exists [lindex $argv 0]]} {
+
+    set usage_chan [switch -regexp -- [lindex $argv 0] \
+                        -?-help {result stdout} \
+                        .* {result stderr}]
+
+    puts -nonewline $usage_chan $usage
+
+    if {$usage_chan eq stderr} {
+        exit 2
+    } else {
+        exit 0
+    }
+}
+
+set libdir [lindex $argv 0]
+cd $libdir
+
+# Make a list of shared library filenames in the specified directory.
+# We assume filesystem objects whose names start with "lib" and end in
+# ".so" or contain ".so." are shared libraries or symlinks to them.
+set possible_shared_lib_filenames [glob -types {f l} lib*.so*]
+set shared_lib_filenames [list]
+foreach {x} $possible_shared_lib_filenames {
+    if {[string match lib*.so $x] ||
+        [string match lib*.so.* $x]} {
+
+        lappend shared_lib_filenames $x
+    }
+}
+unset possible_shared_lib_filenames
+
+# Check that every shared library symlink points to a file in this
+# directory.
+foreach {x} $shared_lib_filenames {
+    if {[file type $x] eq "file"} {continue}
+
+    set link_target [file readlink $x]
+    if {[string first / $link_target] != -1} {
+        error "symlink [list $x] -> [list $link_target] may lead to another directory"
+    }
+}
+
+# Check that every shared library symlink points to a file or symlink
+# whose name starts with the symlink's name followed by a ".", and is
+# longer.
+#
+# FIXME This currently allows 'libfoozer.so.3' to point to
+# 'libfoozer.so.3.17.so.so.so.42.7'.  That should be fixed, as a
+# matter of principle.
+foreach {x} $shared_lib_filenames {
+    if {[file type $x] eq "file"} {continue}
+
+    set link_target [file readlink $x]
+    if {![file exists $link_target]} {
+        set link_target_type {}
+    } else {
+        set link_target_type [file type $link_target]
+    }
+
+    if {[string length $link_target] <= [string length $x.] ||
+        ![string equal -length [string length $x.] $x. $link_target] ||
+        ($link_target_type ne "file" && $link_target_type ne "link")} {
+
+        error "symlink [list $x] -> [list $link_target] is not a valid symlink to a shared library version"
+    }
+}
+
+# Check that all shared library symlinks' and files' names are of the
+# form of a lib*.so name followed by zero or more (".", non-negative
+# decimal number with no unnecessary leading zeroes) pairs.
+foreach {x} $shared_lib_filenames {
+    if {![regexp -all -- {^lib.*\.so(\.(0|[1-9][0-9]*))*$} $x]} {
+        error "file or symlink [list $x] has invalid name"
+    }
+}
+
+# Now decide what to do with each shared library symlink or file.
+#
+# We want to rename each shared library file to the name of the
+# shortest symlink which points to that file and which is not of the
+# form lib*.so .
+#
+# We can do this by first sorting the list ASCIIbetically, then
+# FIXME DESCRIBE INTENDED ALGORITHM                                        
+set shared_lib_filenames [lsort -ascii $shared_lib_filenames]
+set shared_lib_name_actions {}
+set shared_libs_renamed {}
+foreach {x} $shared_lib_filenames {
+    if {[file type $x] eq "link"} {
+        # This is a shared library symlink.  If its target (after
+        # following the whole chain of symlinks) is not in
+        # $shared_libs_renamed yet, then this must also be the symlink
+        # to its target with the shortest name (partly due to the
+        # constraints above on what we allow a symlink to point to,
+        # and partly because of how we sorted the list above).
+
+        if {[regexp -all -- {^lib.*\.so$} $x]} {
+            # This is a shared library symlink of the form lib*.so .
+            # Symlinks of this form are only used by the linker at build
+            # time.  Delete this name.
+
+            lappend shared_lib_name_actions [list rm $x]
+            continue
+        }
+
+        set link_target [file readlink $x]
+        while {[file type $link_target] eq "link"} {
+            # We don't have to worry about symlink loops here.
+            set link_target [file readlink $x]
+        }
+
+        if {[lsearch -exact $shared_libs_renamed $link_target] != -1} {
+            # The target has been renamed already -- just delete this link.
+            lappend shared_lib_name_actions [list rm $x]
+            continue
+        }
+
+        # The target has not been renamed yet.  This must be the
+        # symlink to the target with the shortest name not of the form
+        # lib*.so , and thus it is the name by which the dynamic
+        # loader will attempt to load the library.  Rename it.
+        lappend shared_lib_name_actions [list rm $x]
+        lappend shared_lib_name_actions [list mv $link_target $x]
+        continue
+    }
+
+    if {[file type $x] eq "file"} {
+        # This is a file.  If it is listed in $shared_libs_renamed, we
+        # can now remove it from that list -- no name later in the
+        # list can be a symlink to this file.
+        set i [lsearch -exact $shared_libs_renamed $x]
+        if {i != -1} {
+            set shared_libs_renamed [lreplace $shared_libs_renamed $i $i]
+        }
+        continue
+    }
+
+    # This isn't a file, and it isn't a symlink -- so WTF is this
+    # thing, anyway?  A fish?
+    error "[list $x] foozer?"
+}
+
+# Write the current list of shared library names and the list of
+# rename/delete actions to disk.
+#
+# FIXME Currently, we write these out as single Tcl lists, most likely
+# on a single line, because that is the only format that we can easily
+# emit which can also be parsed easily and unambiguously by another
+# program.  Someday that should be improved; until then, it should be
+# easy enough to write a tiny Tcl program that reads the list and
+# writes out one list element per line or a tiny Tk program that reads
+# the list and sticks it in a listbox widget.
+set library_list {}
+foreach {x} $shared_lib_filenames {
+    set x_type [file type $x]
+    if {$x_type eq "link"} {
+        set extra_info [file readlink $x]
+    } elseif {$x_type eq "file"} {
+        set extra_info {} ;# FIXME This should be a hash of some sort.
+    } else {
+        # can't happen
+        error "[list $x] foozer!"
+    }
+    lappend library_list [list $x $x_type $extra_info]
+}
+set library_list_chan [open ".shared-library-name-list" {WRONLY CREAT EXCL}]
+puts -nonewline $library_list_chan $library_list
+close $library_list_chan
+
+set action_list_chan [open ".shared-library-rename-action-list" {WRONLY CREAT EXCL}]
+puts -nonewline $action_list_chan $shared_lib_name_actions
+close $action_list_chan
+
+# Perform the rename/delete actions.
+#
+# FIXME There should be a -n or --dry-run command-line option to skip this.
+foreach {action} $shared_lib_actions {
+    lassign $action cmd from to
+    switch -exact -- $cmd \
+        rm {
+            file delete -- $from
+        } \
+        mv {
+            file rename -- $from $to
+        }
+}
+





More information about the tor-commits mailing list