Bug 1382697 - Remove native nsinstall; r?glandium draft
authorGregory Szorc <gps@mozilla.com>
Fri, 21 Jul 2017 22:12:31 -0700
changeset 613652 78e920cc841de10a410e7cbe2a22ccb325932f28
parent 613651 e40b94c0bd5e8f047734ed1bd2fe9d9c69a6addc
child 638699 c1eaa24dad7276aa267bd1999e4a9b05192c73c4
push id69829
push usergszorc@mozilla.com
push dateSat, 22 Jul 2017 05:41:44 +0000
reviewersglandium
bugs1382697
milestone56.0a1
Bug 1382697 - Remove native nsinstall; r?glandium We've introduced configure functionality to make the file installation mode configurable. While we haven't yet, we'll likely need to support hard links and some linking primitive on Windows. We know we'll be writing code to handle this in Python for mozpack/install manifests. I'm not keen on duplicating this functionality for nsinstall.c. We already have a Python version of nsinstall (nsinstall.py). It is used on Windows by default. And after recent changes to improve it, it should have feature parity with nsinstall.c. While invoking Python for simple file I/O is heavyweight, so is growing new features on a very crufty C program. It is easier to standardize on Python. So this commit removes the native nsinstall program. For the historical record, nsinstall's copyright line says it was authored by Brendan Eich in 1995. This was likely some of the oldest code in the Firefox repository. But history lives on: there is still a copy of nsinstall.c in the repository as part of NSS. For now... With this change and the transition of non-Windows builds to nsinstall.py (which obeys configure's --with-file-install-mode), there are no meaningful symlinks in the objdir for a full Linux build when --with-file-install-mode=copy is used! The only remaining symlinks are in _virtualenv (which we don't really have control over) and the "ld" symlink in build/unix/gold/ld. I don't think we really care about these since the important thing is for dist/ to be symlink free, which it is. MozReview-Commit-ID: A4OLmlc64lh
config/Makefile.in
config/config.mk
config/moz.build
config/nsinstall.c
config/pathsub.c
config/rules.mk
--- a/config/Makefile.in
+++ b/config/Makefile.in
@@ -7,34 +7,16 @@
 # IMPORTANT: Disable NSBUILDROOT for this directory only, otherwise we have
 # a recursive rule for finding nsinstall and the Perl scripts.
 ifdef NSBUILDROOT
 override NSBUILDROOT :=
 endif
 
 include $(topsrcdir)/config/config.mk
 
-# L10n jobs are doing make -C config manually before anything else,
-# and need nsinstall to be built as a consequence.
-ifdef COMPILE_ENVIRONMENT
-export:: host
-
-ifneq (WINNT,$(HOST_OS_ARCH))
-# Ensure nsinstall is atomically created
-nsinstall$(HOST_BIN_SUFFIX): $(HOST_PROGRAM)
-	cp $^ $@.tmp
-	mv $@.tmp $@
-
-NSINSTALL_EXECUTABLES := nsinstall$(HOST_BIN_SUFFIX)
-NSINSTALL_DEST := $(DIST)/bin
-NSINSTALL_TARGET := host
-INSTALL_TARGETS += NSINSTALL
-endif
-endif
-
 include $(topsrcdir)/config/rules.mk
 
 ifdef WRAP_SYSTEM_INCLUDES
 export-preqs = \
   $(call mkdir_deps,system_wrappers) \
   $(NULL)
 
 export:: $(export-preqs)
--- a/config/config.mk
+++ b/config/config.mk
@@ -426,23 +426,17 @@ endif
 #
 -include $(topsrcdir)/$(MOZ_BUILD_APP)/app-config.mk
 -include $(MY_CONFIG)
 
 ######################################################################
 
 GARBAGE		+= $(DEPENDENCIES) core $(wildcard core.[0-9]*) $(wildcard *.err) $(wildcard *.pure) $(wildcard *_pure_*.o) Templates.DB
 
-NSINSTALL_PY := $(PYTHON) $(abspath $(MOZILLA_DIR)/config/nsinstall.py)
-ifneq (,$(or $(filter WINNT,$(HOST_OS_ARCH)),$(if $(COMPILE_ENVIRONMENT),,1)))
-NSINSTALL = $(NSINSTALL_PY)
-else
-NSINSTALL = $(DEPTH)/config/nsinstall$(HOST_BIN_SUFFIX)
-endif # WINNT
-
+NSINSTALL = $(PYTHON) $(abspath $(MOZILLA_DIR)/config/nsinstall.py)
 
 ifeq ($(FILE_INSTALL_MODE),copy)
 INSTALL = $(NSINSTALL) -t
 else
   # NSDISTMODE can override symlinks
   ifeq ($(NSDISTMODE),copy)
     INSTALL = $(NSINSTALL) -t
   else
--- a/config/moz.build
+++ b/config/moz.build
@@ -13,26 +13,16 @@ DIST_INSTALL = False
 NO_VISIBILITY_FLAGS = True
 
 CONFIGURE_SUBST_FILES += [
     'doxygen.cfg',
     'makefiles/test/Makefile',
     'tests/src-simple/Makefile',
 ]
 
-if CONFIG['HOST_OS_ARCH'] != 'WINNT':
-    HOST_SOURCES += [
-        'nsinstall.c',
-        'pathsub.c',
-    ]
-    # stdc++compat depends on config/export, so avoid a circular
-    # dependency added by HostProgram depending on stdc++compat,
-    # while the program here is in C.
-    HostProgram('nsinstall_real', c_only=True)
-
 if CONFIG['MOZ_SYSTEM_ICU']:
     DEFINES['MOZ_SYSTEM_ICU'] = True
 
 PYTHON_UNITTEST_MANIFESTS += [
     'tests/python.ini',
 ]
 
 if CONFIG['GNU_CC'] and CONFIG['MOZ_OPTIMIZE']:
deleted file mode 100644
--- a/config/nsinstall.c
+++ /dev/null
@@ -1,451 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-/*
-** Netscape portable install command.
-**
-** Brendan Eich, 7/20/95
-*/
-#include <stdio.h>  /* OSF/1 requires this before grp.h, so put it first */
-#include <assert.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <dirent.h>
-#include <limits.h>
-#include <grp.h>
-#include <pwd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <utime.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include "pathsub.h"
-
-#ifdef HAVE_GETOPT_H
-#include <getopt.h>
-#endif
-
-#ifdef SUNOS4
-#include "sunos4.h"
-#endif
-
-#ifdef NEXTSTEP
-#include <bsd/libc.h>
-#endif
-
-#ifdef __QNX__
-#include <unix.h>
-#endif
-
-#ifdef NEED_S_ISLNK
-#if !defined(S_ISLNK) && defined(S_IFLNK)
-#define S_ISLNK(a)	(((a) & S_IFMT) == S_IFLNK)
-#endif
-#endif
-
-#ifndef _DIRECTORY_SEPARATOR
-#define _DIRECTORY_SEPARATOR "/"
-#endif /* _DIRECTORY_SEPARATOR */
-
-#ifdef NEED_FCHMOD_PROTO
-extern int fchmod(int fildes, mode_t mode);
-#endif
-
-static void
-usage(void)
-{
-    fprintf(stderr,
-	"usage: %s [-C cwd] [-L linkprefix] [-m mode] [-o owner] [-g group]\n"
-	"       %*s [-DdltR] file [file ...] directory\n",
-	program, (int) strlen(program), "");
-    exit(2);
-}
-
-static int
-mkdirs(char *path, mode_t mode)
-{
-    char *cp;
-    struct stat sb;
-    int res;
-    int l;
-
-    /* strip trailing "/." */
-    l = strlen(path);
-    if(l > 1 && path[l - 1] == '.' && path[l - 2] == '/')
-        path[l - 2] = 0;
-
-    while (*path == '/' && path[1] == '/')
-	path++;
-    for (cp = strrchr(path, '/'); cp && cp != path && *(cp - 1) == '/'; cp--);
-    if (cp && cp != path) {
-	*cp = '\0';
-	if ((lstat(path, &sb) < 0 || !S_ISDIR(sb.st_mode)) &&
-	    mkdirs(path, mode) < 0) {
-	    return -1;
-	}
-	*cp = '/';
-    }
-    
-    res = mkdir(path, mode);
-    if ((res != 0) && (errno == EEXIST))
-      return 0;
-    else
-      return res;
-}
-
-static uid_t
-touid(char *owner)
-{
-    struct passwd *pw;
-    uid_t uid;
-    char *cp;
-
-    pw = getpwnam(owner);
-    if (pw)
-	return pw->pw_uid;
-    uid = strtol(owner, &cp, 0);
-    if (uid == 0 && cp == owner)
-	fail("cannot find uid for %s", owner);
-    return uid;
-}
-
-static gid_t
-togid(char *group)
-{
-    struct group *gr;
-    gid_t gid;
-    char *cp;
-
-    gr = getgrnam(group);
-    if (gr)
-	return gr->gr_gid;
-    gid = strtol(group, &cp, 0);
-    if (gid == 0 && cp == group)
-	fail("cannot find gid for %s", group);
-    return gid;
-}
-
-static void
-copyfile( char *name, char *toname, mode_t mode, char *group, char *owner,
-          int dotimes, uid_t uid, gid_t gid )
-{
-  int fromfd, tofd = -1, cc, wc, exists;
-  char buf[BUFSIZ], *bp;
-  struct stat sb, tosb;
-  struct utimbuf utb;
-
-  exists = (lstat(toname, &tosb) == 0);
-
-  fromfd = open(name, O_RDONLY);
-  if (fromfd < 0 || fstat(fromfd, &sb) < 0)
-    fail("cannot access %s", name);
-  if (exists) {
-    if (S_ISREG(tosb.st_mode)) {
-      /* See if we can open it. This is more reliable than 'access'. */
-      tofd = open(toname, O_CREAT | O_WRONLY, 0666);
-    }
-    if (tofd < 0) {
-      (void) (S_ISDIR(tosb.st_mode) ? rmdir : unlink)(toname);
-    }
-  }
-  if (tofd < 0) {
-    tofd = open(toname, O_CREAT | O_WRONLY, 0666);
-    if (tofd < 0)
-      fail("cannot create %s", toname);
-  }
-
-  bp = buf;
-  while ((cc = read(fromfd, bp, sizeof buf)) > 0)
-  {
-    while ((wc = write(tofd, bp, (unsigned int)cc)) > 0)
-    {
-      if ((cc -= wc) == 0)
-        break;
-      bp += wc;
-    }
-    if (wc < 0)
-      fail("cannot write to %s", toname);
-  }
-  if (cc < 0)
-    fail("cannot read from %s", name);
-
-  if (ftruncate(tofd, sb.st_size) < 0)
-    fail("cannot truncate %s", toname);
-#if !defined(VMS)
-  if (dotimes)
-  {
-    utb.actime = sb.st_atime;
-    utb.modtime = sb.st_mtime;
-    if (utime(toname, &utb) < 0)
-      fail("cannot set times of %s", toname);
-  }
-#ifdef HAVE_FCHMOD
-  if (fchmod(tofd, mode) < 0)
-#else
-  if (chmod(toname, mode) < 0)
-#endif
-    fail("cannot change mode of %s", toname);
-#endif
-  if ((owner || group) && fchown(tofd, uid, gid) < 0)
-    fail("cannot change owner of %s", toname);
-
-  /* Must check for delayed (NFS) write errors on close. */
-  if (close(tofd) < 0)
-    fail("cannot write to %s", toname);
-  close(fromfd);
-#if defined(VMS)
-  if (chmod(toname, (mode & (S_IREAD | S_IWRITE))) < 0)
-    fail("cannot change mode of %s", toname);
-  if (dotimes)
-  {
-    utb.actime = sb.st_atime;
-    utb.modtime = sb.st_mtime;
-    if (utime(toname, &utb) < 0)
-      fail("cannot set times of %s", toname);
-  }
-#endif
-}
-
-static void
-copydir( char *from, char *to, mode_t mode, char *group, char *owner,
-         int dotimes, uid_t uid, gid_t gid)
-{
-  DIR *dir;
-  struct dirent *ep;
-  struct stat sb;
-  char *base, *destdir, *direntry, *destentry;
-
-  base = xbasename(from);
-
-  /* create destination directory */
-  destdir = xmalloc((unsigned int)(strlen(to) + 1 + strlen(base) + 1));
-  sprintf(destdir, "%s%s%s", to, _DIRECTORY_SEPARATOR, base);
-  if (mkdirs(destdir, mode) != 0) {
-    fail("cannot make directory %s\n", destdir);
-    free(destdir);
-    return;
-  }
-
-  if (!(dir = opendir(from))) {
-    fail("cannot open directory %s\n", from);
-    free(destdir);
-    return;
-  }
-
-  direntry = xmalloc((unsigned int)PATH_MAX);
-  destentry = xmalloc((unsigned int)PATH_MAX);
-
-  while ((ep = readdir(dir)))
-  {
-    if (strcmp(ep->d_name, ".") == 0 || strcmp(ep->d_name, "..") == 0)
-      continue;
-
-    sprintf(direntry, "%s/%s", from, ep->d_name);
-    sprintf(destentry, "%s%s%s", destdir, _DIRECTORY_SEPARATOR, ep->d_name);
-
-    if (stat(direntry, &sb) == 0 && S_ISDIR(sb.st_mode))
-      copydir( direntry, destdir, mode, group, owner, dotimes, uid, gid );
-    else
-      copyfile( direntry, destentry, mode, group, owner, dotimes, uid, gid );
-  }
-
-  free(destdir);
-  free(direntry);
-  free(destentry);
-  closedir(dir);
-}
-
-int
-main(int argc, char **argv)
-{
-    int onlydir, dodir, dolink, dorelsymlink, dotimes, opt, len, lplen, tdlen, bnlen, exists;
-    mode_t mode = 0755;
-    char *linkprefix, *owner, *group, *cp, *cwd, *todir, *toname, *name, *base, *linkname, buf[BUFSIZ];
-    uid_t uid;
-    gid_t gid;
-    struct stat sb, tosb, fromsb;
-
-    program = argv[0];
-    cwd = linkname = linkprefix = owner = group = 0;
-    onlydir = dodir = dolink = dorelsymlink = dotimes = lplen = 0;
-
-    while ((opt = getopt(argc, argv, "C:DdlL:Rm:o:g:t")) != EOF) {
-	switch (opt) {
-	  case 'C':
-	    cwd = optarg;
-	    break;
-	  case 'D':
-	    onlydir = 1;
-	    break;
-	  case 'd':
-	    dodir = 1;
-	    break;
-	  case 'L':
-	    linkprefix = optarg;
-	    lplen = strlen(linkprefix);
-	    dolink = 1;
-	    break;
-	  case 'R':
-	    dolink = dorelsymlink = 1;
-	    break;
-	  case 'm':
-	    mode = strtoul(optarg, &cp, 8);
-	    if (mode == 0 && cp == optarg)
-		usage();
-	    break;
-	  case 'o':
-	    owner = optarg;
-	    break;
-	  case 'g':
-	    group = optarg;
-	    break;
-	  case 't':
-	    dotimes = 1;
-	    break;
-	  default:
-	    usage();
-	}
-    }
-
-    argc -= optind;
-    argv += optind;
-    if (argc < 2 - onlydir)
-	usage();
-
-    todir = argv[argc-1];
-    if ((stat(todir, &sb) < 0 || !S_ISDIR(sb.st_mode)) &&
-	mkdirs(todir, 0777) < 0) {
-	fail("cannot make directory %s", todir);
-    }
-    if (onlydir)
-	return 0;
-
-    if (!cwd) {
-#ifndef NEEDS_GETCWD
-#ifndef GETCWD_CANT_MALLOC
-	cwd = getcwd(0, PATH_MAX);
-#else
-	cwd = malloc(PATH_MAX + 1);
-	cwd = getcwd(cwd, PATH_MAX);
-#endif
-#else
-	cwd = malloc(PATH_MAX + 1);
-	cwd = getwd(cwd);
-#endif
-    }
-
-    xchdir(todir);
-#ifndef NEEDS_GETCWD
-#ifndef GETCWD_CANT_MALLOC
-    todir = getcwd(0, PATH_MAX);
-#else
-    todir = malloc(PATH_MAX + 1);
-    todir = getcwd(todir, PATH_MAX);
-#endif
-#else
-    todir = malloc(PATH_MAX + 1);
-    todir = getwd(todir);
-#endif
-    tdlen = strlen(todir);
-    xchdir(cwd);
-    tdlen = strlen(todir);
-
-    uid = owner ? touid(owner) : (uid_t)(-1);
-    gid = group ? togid(group) : (gid_t)(-1);
-
-    while (--argc > 0) {
-	name = *argv++;
-	len = strlen(name);
-	base = xbasename(name);
-	bnlen = strlen(base);
-	toname = xmalloc((unsigned int)(tdlen + 1 + bnlen + 1));
-	sprintf(toname, "%s%s%s", todir, _DIRECTORY_SEPARATOR, base);
-	exists = (lstat(toname, &tosb) == 0);
-
-	if (dodir) {
-	    /* -d means create a directory, always */
-	    if (exists && !S_ISDIR(tosb.st_mode)) {
-		(void) unlink(toname);
-		exists = 0;
-	    }
-	    if (!exists && mkdir(toname, mode) < 0)
-		fail("cannot make directory %s", toname);
-	    if ((owner || group) && chown(toname, uid, gid) < 0)
-		fail("cannot change owner of %s", toname);
-	} else if (dolink) {
-            if (access(name, R_OK) != 0) {
-                fail("cannot access %s", name);
-            }
-	    if (*name == '/') {
-		/* source is absolute pathname, link to it directly */
-		linkname = 0;
-	    } else {
-		if (linkprefix) {
-		    /* -L prefixes names with a $cwd arg. */
-		    len += lplen + 1;
-		    linkname = xmalloc((unsigned int)(len + 1));
-		    sprintf(linkname, "%s/%s", linkprefix, name);
-		} else if (dorelsymlink) {
-		    /* Symlink the relative path from todir to source name. */
-		    linkname = xmalloc(PATH_MAX);
-
-		    if (*todir == '/') {
-			/* todir is absolute: skip over common prefix. */
-			lplen = relatepaths(todir, cwd, linkname);
-			strcpy(linkname + lplen, name);
-		    } else {
-			/* todir is named by a relative path: reverse it. */
-			reversepath(todir, name, len, linkname);
-			xchdir(cwd);
-		    }
-
-		    len = strlen(linkname);
-		}
-		name = linkname;
-	    }
-
-	    /* Check for a pre-existing symlink with identical content. */
-	    if (exists && (!S_ISLNK(tosb.st_mode) ||
-						readlink(toname, buf, sizeof buf) != len ||
-						strncmp(buf, name, (unsigned int)len) != 0 || 
-			((stat(name, &fromsb) == 0) &&
-			 (fromsb.st_mtime > tosb.st_mtime) 
-			 ))) {
-		(void) (S_ISDIR(tosb.st_mode) ? rmdir : unlink)(toname);
-		exists = 0;
-	    }
-	    if (!exists && symlink(name, toname) < 0)
-		fail("cannot make symbolic link %s", toname);
-#ifdef HAVE_LCHOWN
-	    if ((owner || group) && lchown(toname, uid, gid) < 0)
-		fail("cannot change owner of %s", toname);
-#endif
-
-	    if (linkname) {
-		free(linkname);
-		linkname = 0;
-	    }
-	} else {
-	    /* Copy from name to toname, which might be the same file. */
-      if( stat(name, &sb) == 0 && S_IFDIR & sb.st_mode )
-      {
-        /* then is directory: must explicitly create destination dir  */
-        /*  and manually copy files over                              */
-        copydir( name, todir, mode, group, owner, dotimes, uid, gid );
-      } 
-      else
-      {
-        copyfile(name, toname, mode, group, owner, dotimes, uid, gid);
-      }
-    }
-
-	free(toname);
-    }
-
-    free(cwd);
-    free(todir);
-    return 0;
-}
deleted file mode 100644
--- a/config/pathsub.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-/*
-** Pathname subroutines.
-**
-** Brendan Eich, 8/29/95
-*/
-#include <assert.h>
-#include <sys/types.h>
-#include <dirent.h>
-#include <errno.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/stat.h>
-#include "pathsub.h"
-
-#ifdef USE_REENTRANT_LIBC
-#include <libc_r.h>
-#endif
-
-#ifdef SUNOS4
-#include "sunos4.h"
-#endif
-
-#ifndef D_INO
-#define D_INO	d_ino
-#endif
-
-char *program;
-
-void
-fail(const char *format, ...)
-{
-    int error;
-    va_list ap;
-
-#ifdef USE_REENTRANT_LIBC
-    R_STRERROR_INIT_R();
-#endif
-
-    error = errno;
-    fprintf(stderr, "%s: ", program);
-    va_start(ap, format);
-    vfprintf(stderr, format, ap);
-    va_end(ap);
-    if (error) {
-
-#ifdef USE_REENTRANT_LIBC
-    R_STRERROR_R(errno);
-	fprintf(stderr, ": %s", r_strerror_r);
-#else
-	fprintf(stderr, ": %s", strerror(errno));
-#endif
-    }
-
-    putc('\n', stderr);
-    exit(1);
-}
-
-char *
-getcomponent(char *path, char *name)
-{
-    if (*path == '\0')
-	return 0;
-    if (*path == '/') {
-	*name++ = '/';
-    } else {
-	do {
-	    *name++ = *path++;
-	} while (*path != '/' && *path != '\0');
-    }
-    *name = '\0';
-    while (*path == '/')
-	path++;
-    return path;
-}
-
-#ifdef LAME_READDIR
-#include <sys/param.h>
-/*
-** The static buffer in Unixware's readdir is too small.
-*/
-struct dirent *readdir(DIR *d)
-{
-        static struct dirent *buf = NULL;
-
-        if(buf == NULL)
-                buf = (struct dirent *) malloc(sizeof(struct dirent) + MAXPATHLEN);
-        return(readdir_r(d, buf));
-}
-#endif
-
-char *
-ino2name(ino_t ino)
-{
-    DIR *dp;
-    struct dirent *ep;
-    char *name;
-
-    dp = opendir("..");
-    if (!dp)
-	fail("cannot read parent directory");
-    for (;;) {
-	if (!(ep = readdir(dp)))
-	    fail("cannot find current directory");
-	if (ep->D_INO == ino)
-	    break;
-    }
-    name = xstrdup(ep->d_name);
-    closedir(dp);
-    return name;
-}
-
-void *
-xmalloc(size_t size)
-{
-    void *p = malloc(size);
-    if (!p)
-	fail("cannot allocate %u bytes", size);
-    return p;
-}
-
-char *
-xstrdup(char *s)
-{
-    return strcpy(xmalloc(strlen(s) + 1), s);
-}
-
-char *
-xbasename(char *path)
-{
-    char *cp;
-
-    while ((cp = strrchr(path, '/')) && cp[1] == '\0')
-	*cp = '\0';
-    if (!cp) return path;
-    return cp + 1;
-}
-
-void
-xchdir(const char *dir)
-{
-    if (chdir(dir) < 0)
-	fail("cannot change directory to %s", dir);
-}
-
-int
-relatepaths(char *from, char *to, char *outpath)
-{
-    char *cp, *cp2;
-    int len;
-    char buf[NAME_MAX];
-
-    assert(*from == '/' && *to == '/');
-    for (cp = to, cp2 = from; *cp == *cp2; cp++, cp2++)
-	if (*cp == '\0')
-	    break;
-    while (cp[-1] != '/')
-	cp--, cp2--;
-    if (cp - 1 == to) {
-	/* closest common ancestor is /, so use full pathname */
-	len = strlen(strcpy(outpath, to));
-	if (outpath[len] != '/') {
-	    outpath[len++] = '/';
-	    outpath[len] = '\0';
-	}
-    } else {
-	len = 0;
-	while ((cp2 = getcomponent(cp2, buf)) != 0) {
-	    strcpy(outpath + len, "../");
-	    len += 3;
-	}
-	while ((cp = getcomponent(cp, buf)) != 0) {
-	    sprintf(outpath + len, "%s/", buf);
-	    len += strlen(outpath + len);
-	}
-    }
-    return len;
-}
-
-void
-reversepath(char *inpath, char *name, int len, char *outpath)
-{
-    char *cp, *cp2;
-    char buf[NAME_MAX];
-    struct stat sb;
-
-    cp = strcpy(outpath + PATH_MAX - (len + 1), name);
-    cp2 = inpath;
-    while ((cp2 = getcomponent(cp2, buf)) != 0) {
-	if (strcmp(buf, ".") == 0)
-	    continue;
-	if (strcmp(buf, "..") == 0) {
-	    if (stat(".", &sb) < 0)
-		fail("cannot stat current directory");
-	    name = ino2name(sb.st_ino);
-	    len = strlen(name);
-	    cp -= len + 1;
-	    strcpy(cp, name);
-	    cp[len] = '/';
-	    free(name);
-	    xchdir("..");
-	} else {
-	    cp -= 3;
-	    strncpy(cp, "../", 3);
-	    xchdir(buf);
-	}
-    }
-    strcpy(outpath, cp);
-}
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -1376,43 +1376,31 @@ endif
 # Additionally, a FOO_TARGET variable may be added to indicate the target for
 # which the files and executables are installed. Default is "libs".
 #
 # Finally, a FOO_KEEP_PATH variable may be set to 1 to indicate the paths given
 # in FOO_FILES/FOO_EXECUTABLES are to be kept at the destination. That is,
 # if FOO_FILES is bar/baz/qux.h, and FOO_DEST is $(DIST)/include, the installed
 # file would be $(DIST)/include/bar/baz/qux.h instead of $(DIST)/include/qux.h
 
-# If we're using binary nsinstall and it's not built yet, fallback to python nsinstall.
-ifneq (,$(filter $(DEPTH)/config/nsinstall$(HOST_BIN_SUFFIX),$(install_cmd)))
-ifeq (,$(wildcard $(DEPTH)/config/nsinstall$(HOST_BIN_SUFFIX)))
-nsinstall_is_usable = $(if $(wildcard $(DEPTH)/config/nsinstall$(HOST_BIN_SUFFIX)),yes)
-
-define install_cmd_override
-$(1): install_cmd = $$(if $$(nsinstall_is_usable),$$(INSTALL),$$(NSINSTALL_PY) -t) $$(1)
-endef
-endif
-endif
-
 install_target_tier = $(or $($(1)_TARGET),libs)
 INSTALL_TARGETS_TIERS := $(sort $(foreach category,$(INSTALL_TARGETS),$(call install_target_tier,$(category))))
 
 install_target_result = $($(1)_DEST:%/=%)/$(if $($(1)_KEEP_PATH),$(2),$(notdir $(2)))
 install_target_files = $(foreach file,$($(1)_FILES),$(call install_target_result,$(category),$(file)))
 install_target_executables = $(foreach file,$($(1)_EXECUTABLES),$(call install_target_result,$(category),$(file)))
 
 # Work around a GNU make 3.81 bug where it gives $< the wrong value.
 # See details in bug 934864.
 define create_dependency
 $(1): $(2)
 $(1): $(2)
 endef
 
 define install_target_template
-$(call install_cmd_override,$(2))
 $(call create_dependency,$(2),$(1))
 endef
 
 $(foreach category,$(INSTALL_TARGETS),\
   $(if $($(category)_DEST),,$(error Missing $(category)_DEST)) \
   $(foreach tier,$(call install_target_tier,$(category)),\
     $(eval INSTALL_TARGETS_FILES_$(tier) += $(call install_target_files,$(category))) \
     $(eval INSTALL_TARGETS_EXECUTABLES_$(tier) += $(call install_target_executables,$(category))) \