1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-15 20:29:03 +00:00

Add an uninstall option to ndiff's setup.py

This commit is contained in:
dmiller
2014-11-13 13:24:41 +00:00
parent ce340ba67b
commit 6271177458
4 changed files with 248 additions and 11 deletions

View File

@@ -83,6 +83,7 @@ INSTALLZENMAP=@INSTALLZENMAP@
INSTALLNDIFF=@INSTALLNDIFF@ INSTALLNDIFF=@INSTALLNDIFF@
INSTALLNPING=@INSTALLNPING@ INSTALLNPING=@INSTALLNPING@
UNINSTALLZENMAP=@UNINSTALLZENMAP@ UNINSTALLZENMAP=@UNINSTALLZENMAP@
UNINSTALLNDIFF=@UNINSTALLNDIFF@
UNINSTALLNPING=@UNINSTALLNPING@ UNINSTALLNPING=@UNINSTALLNPING@
ifneq (@LIBLUA_LIBS@,) ifneq (@LIBLUA_LIBS@,)
@@ -365,7 +366,7 @@ install-nping: $(NPINGDIR)/nping
install: install-nmap $(INSTALLNSE) $(INSTALLZENMAP) @NCAT_INSTALL@ @NMAP_UPDATE_INSTALL@ $(INSTALLNDIFF) $(INSTALLNPING) install: install-nmap $(INSTALLNSE) $(INSTALLZENMAP) @NCAT_INSTALL@ @NMAP_UPDATE_INSTALL@ $(INSTALLNDIFF) $(INSTALLNPING)
@echo "NMAP SUCCESSFULLY INSTALLED" @echo "NMAP SUCCESSFULLY INSTALLED"
uninstall: uninstall-nmap $(UNINSTALLZENMAP) @NCAT_UNINSTALL@ @NMAP_UPDATE_UNINSTALL@ $(UNINSTALLNPING) uninstall: uninstall-nmap $(UNINSTALLZENMAP) @NCAT_UNINSTALL@ @NMAP_UPDATE_UNINSTALL@ $(UNINSTALLNDIFF) $(UNINSTALLNPING)
uninstall-nmap: uninstall-nmap:
rm -f $(DESTDIR)$(bindir)/$(TARGET) rm -f $(DESTDIR)$(bindir)/$(TARGET)
@@ -382,6 +383,9 @@ uninstall-zenmap:
fi fi
rm -f $(DESTDIR)$(bindir)/xnmap rm -f $(DESTDIR)$(bindir)/xnmap
uninstall-ndiff:
cd $(NDIFFDIR) && $(PYTHON) setup.py uninstall
uninstall-ncat: uninstall-ncat:
@cd $(NCATDIR) && $(MAKE) uninstall @cd $(NCATDIR) && $(MAKE) uninstall

4
configure vendored
View File

@@ -690,6 +690,7 @@ ZENMAPDIR
NDIFF_DIST_CLEAN NDIFF_DIST_CLEAN
NDIFF_CLEAN NDIFF_CLEAN
NDIFF_CHECK NDIFF_CHECK
UNINSTALLNDIFF
INSTALLNDIFF INSTALLNDIFF
BUILDNDIFF BUILDNDIFF
NDIFFDIR NDIFFDIR
@@ -5711,12 +5712,14 @@ fi
if test "$with_ndiff" = "no"; then if test "$with_ndiff" = "no"; then
BUILDNDIFF="" BUILDNDIFF=""
INSTALLNDIFF="" INSTALLNDIFF=""
UNINSTALLNDIFF=""
NDIFF_CHECK="" NDIFF_CHECK=""
NDIFF_CLEAN="" NDIFF_CLEAN=""
NDIFF_DIST_CLEAN="" NDIFF_DIST_CLEAN=""
else else
BUILDNDIFF=build-ndiff BUILDNDIFF=build-ndiff
INSTALLNDIFF=install-ndiff INSTALLNDIFF=install-ndiff
UNINSTALLNDIFF=uninstall-ndiff
NDIFF_CHECK="ndiff_check" NDIFF_CHECK="ndiff_check"
NDIFF_CLEAN=ndiff_clean NDIFF_CLEAN=ndiff_clean
NDIFF_DIST_CLEAN=ndiff_dist_clean NDIFF_DIST_CLEAN=ndiff_dist_clean
@@ -5728,6 +5731,7 @@ fi
ZENMAPDIR=zenmap ZENMAPDIR=zenmap
# Do they want Zenmap? # Do they want Zenmap?

View File

@@ -232,12 +232,14 @@ fi
if test "$with_ndiff" = "no"; then if test "$with_ndiff" = "no"; then
BUILDNDIFF="" BUILDNDIFF=""
INSTALLNDIFF="" INSTALLNDIFF=""
UNINSTALLNDIFF=""
NDIFF_CHECK="" NDIFF_CHECK=""
NDIFF_CLEAN="" NDIFF_CLEAN=""
NDIFF_DIST_CLEAN="" NDIFF_DIST_CLEAN=""
else else
BUILDNDIFF=build-ndiff BUILDNDIFF=build-ndiff
INSTALLNDIFF=install-ndiff INSTALLNDIFF=install-ndiff
UNINSTALLNDIFF=uninstall-ndiff
NDIFF_CHECK="ndiff_check" NDIFF_CHECK="ndiff_check"
NDIFF_CLEAN=ndiff_clean NDIFF_CLEAN=ndiff_clean
NDIFF_DIST_CLEAN=ndiff_dist_clean NDIFF_DIST_CLEAN=ndiff_dist_clean
@@ -245,6 +247,7 @@ fi
AC_SUBST(NDIFFDIR) AC_SUBST(NDIFFDIR)
AC_SUBST(BUILDNDIFF) AC_SUBST(BUILDNDIFF)
AC_SUBST(INSTALLNDIFF) AC_SUBST(INSTALLNDIFF)
AC_SUBST(UNINSTALLNDIFF)
AC_SUBST(NDIFF_CHECK) AC_SUBST(NDIFF_CHECK)
AC_SUBST(NDIFF_CLEAN) AC_SUBST(NDIFF_CLEAN)
AC_SUBST(NDIFF_DIST_CLEAN) AC_SUBST(NDIFF_DIST_CLEAN)

View File

@@ -6,14 +6,32 @@ import os
import os.path import os.path
import re import re
from stat import *
import distutils.command import distutils.command
import distutils.command.install import distutils.command.install
import distutils.core import distutils.core
import distutils.cmd import distutils.cmd
import distutils.errors import distutils.errors
from distutils import log
from distutils.command.install import install from distutils.command.install import install
APP_NAME = "ndiff" APP_NAME = "ndiff"
# The name of the file used to record the list of installed files, so that the
# uninstall command can remove them.
INSTALLED_FILES_NAME = "INSTALLED_FILES"
# path_startswith and path_strip_prefix are used to deal with the installation
# root (--root option, also known as DESTDIR).
def path_startswith(path, prefix):
"""Returns True if path starts with prefix. It's a little more intelligent
than str.startswith because it normalizes the paths to remove multiple
directory separators and down-up traversals."""
path = os.path.normpath(path)
prefix = os.path.normpath(prefix)
return path.startswith(prefix)
def path_strip_prefix(path, prefix): def path_strip_prefix(path, prefix):
"""Return path stripped of its directory prefix if it starts with prefix, """Return path stripped of its directory prefix if it starts with prefix,
@@ -42,10 +60,9 @@ def path_strip_prefix(path, prefix):
return path return path
############################################################################### ###############################################################################
# Distutils subclasses # Distutils subclasses
class null_command(distutils.cmd.Command): class null_command(distutils.cmd.Command):
"""This is a dummy distutils command that does nothing. We use it to """This is a dummy distutils command that does nothing. We use it to
replace the install_egg_info and avoid installing a .egg-info file, because replace the install_egg_info and avoid installing a .egg-info file, because
@@ -56,6 +73,9 @@ class null_command(distutils.cmd.Command):
def finalize_options(self): def finalize_options(self):
pass pass
def get_outputs(self):
return ()
def run(self): def run(self):
pass pass
@@ -67,6 +87,11 @@ class checked_install(distutils.command.install.install):
""" """
def finalize_options(self): def finalize_options(self):
# Ubuntu's python2.6-2.6.4-0ubuntu3 package changes sys.prefix in
# install.finalize_options when sys.prefix is "/usr/local" (our
# default). Because we need the unchanged value later, remember it
# here.
self.saved_prefix = sys.prefix
try: try:
distutils.command.install.install.finalize_options(self) distutils.command.install.install.finalize_options(self)
except distutils.errors.DistutilsPlatformError, e: except distutils.errors.DistutilsPlatformError, e:
@@ -85,32 +110,233 @@ Installing your distribution's python-dev package may solve this problem.""")
app_file = open(app_file_name, "r") app_file = open(app_file_name, "r")
lines = app_file.readlines() lines = app_file.readlines()
app_file.close() app_file.close()
for i in range(len(lines)): for i in range(len(lines)):
if re.match(r'^INSTALL_LIB =', lines[i]): if re.match(r'^INSTALL_LIB =', lines[i]):
lines[i] = "INSTALL_LIB = %s\n" % repr(modules_dir) lines[i] = "INSTALL_LIB = %s\n" % repr(modules_dir)
break break
else: else:
raise ValueError( raise ValueError(
"INSTALL_LIB replacement not found in %s" % app_file_name) "INSTALL_LIB replacement not found in %s" % app_file_name)
app_file = open(app_file_name, "w") app_file = open(app_file_name, "w")
app_file.writelines(lines) app_file.writelines(lines)
app_file.close() app_file.close()
def run(self): def run(self):
install.run(self) install.run(self)
# These below are from Zenmap. We're only using set_modules_path right now, but we might consider whether the others would be useful (or, if not, whether we should remove them from Zenmap). # These below are from Zenmap. We're only using set_modules_path right now, but
# we might consider whether the others would be useful (or, if not, whether we
# should remove them from Zenmap).
# self.set_perms() # self.set_perms()
self.set_modules_path() self.set_modules_path()
# self.fix_paths() # self.fix_paths()
# self.create_uninstaller() self.create_uninstaller()
# self.write_installed_files() self.write_installed_files()
def get_installed_files(self):
"""Return a list of installed files and directories, each prefixed with
the installation root if given. The list of installed directories
doesn't come from distutils so it may be incomplete."""
installed_files = self.get_outputs()
for package in self.distribution.py_modules:
dir = package.replace(".", "/")
installed_files.append(os.path.join(self.install_lib, dir))
installed_files.append(
os.path.join(self.install_scripts, "uninstall_" + APP_NAME))
return installed_files
def create_uninstaller(self):
uninstaller_filename = os.path.join(
self.install_scripts, "uninstall_" + APP_NAME)
uninstaller = """\
#!/usr/bin/env python
import errno, os, os.path, sys
print 'Uninstall %(name)s'
answer = raw_input('Are you sure that you want to uninstall '
'%(name)s (yes/no) ')
if answer != 'yes' and answer != 'y':
print 'Not uninstalling.'
sys.exit(0)
""" % {'name': APP_NAME}
installed_files = []
for output in self.get_installed_files():
if self.root is not None:
# If we have a root (DESTDIR), we need to strip it off the
# front of paths so the uninstaller runs on the target host.
# The path manipulations are tricky, but made easier because
# the uninstaller only has to run on Unix.
if not path_startswith(output, self.root):
# This should never happen (everything gets installed
# inside the root), but if it does, be safe and don't
# delete anything.
uninstaller += ("print '%s was not installed inside "
"the root %s; skipping.'\n" % (output, self.root))
continue
output = path_strip_prefix(output, self.root)
assert os.path.isabs(output)
installed_files.append(output)
uninstaller += """\
INSTALLED_FILES = (
"""
for file in installed_files:
uninstaller += " %s,\n" % repr(file)
uninstaller += """\
)
# Split the list into lists of files and directories.
files = []
dirs = []
for path in INSTALLED_FILES:
if os.path.isfile(path) or os.path.islink(path):
files.append(path)
elif os.path.isdir(path):
dirs.append(path)
# Delete the files.
for file in files:
print "Removing '%s'." % file
try:
os.remove(file)
except OSError, e:
print >> sys.stderr, ' Error: %s.' % str(e)
# Delete the directories. First reverse-sort the normalized paths by
# length so that child directories are deleted before their parents.
dirs = [os.path.normpath(dir) for dir in dirs]
dirs.sort(key = len, reverse = True)
for dir in dirs:
try:
print "Removing the directory '%s'." % dir
os.rmdir(dir)
except OSError, e:
if e.errno == errno.ENOTEMPTY:
print "Directory '%s' not empty; not removing." % dir
else:
print >> sys.stderr, str(e)
"""
uninstaller_file = open(uninstaller_filename, 'w')
uninstaller_file.write(uninstaller)
uninstaller_file.close()
# Set exec bit for uninstaller
mode = ((os.stat(uninstaller_filename)[ST_MODE]) | 0555) & 07777
os.chmod(uninstaller_filename, mode)
def set_modules_path(self):
app_file_name = os.path.join(self.install_scripts, APP_NAME)
# Find where the modules are installed. distutils will put them in
# self.install_lib, but that path can contain the root (DESTDIR), so we
# must strip it off if necessary.
modules_dir = self.install_lib
if self.root is not None:
modules_dir = path_strip_prefix(modules_dir, self.root)
app_file = open(app_file_name, "r")
lines = app_file.readlines()
app_file.close()
for i in range(len(lines)):
if re.match(r'^INSTALL_LIB =', lines[i]):
lines[i] = "INSTALL_LIB = %s\n" % repr(modules_dir)
break
else:
raise ValueError(
"INSTALL_LIB replacement not found in %s" % app_file_name)
app_file = open(app_file_name, "w")
app_file.writelines(lines)
app_file.close()
def write_installed_files(self):
"""Write a list of installed files for use by the uninstall command.
This is similar to what happens with the --record option except that it
doesn't strip off the installation root, if any. File names containing
newline characters are not handled."""
if INSTALLED_FILES_NAME == self.record:
distutils.log.warn("warning: installation record is overwriting "
"--record file '%s'." % self.record)
f = open(INSTALLED_FILES_NAME, "w")
try:
for output in self.get_installed_files():
assert "\n" not in output
print >> f, output
finally:
f.close()
class my_uninstall(distutils.cmd.Command):
"""A distutils command that performs uninstallation. It reads the list of
installed files written by the install command."""
command_name = "uninstall"
description = "uninstall installed files recorded in '%s'" % (
INSTALLED_FILES_NAME)
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
# Read the list of installed files.
try:
f = open(INSTALLED_FILES_NAME, "r")
except IOError, e:
if e.errno == errno.ENOENT:
log.error("Couldn't open the installation record '%s'. "
"Have you installed yet?" % INSTALLED_FILES_NAME)
return
installed_files = [file.rstrip("\n") for file in f.readlines()]
f.close()
# Delete the installation record too.
installed_files.append(INSTALLED_FILES_NAME)
# Split the list into lists of files and directories.
files = []
dirs = []
for path in installed_files:
if os.path.isfile(path) or os.path.islink(path):
files.append(path)
elif os.path.isdir(path):
dirs.append(path)
# Delete the files.
for file in files:
log.info("Removing '%s'." % file)
try:
if not self.dry_run:
os.remove(file)
except OSError, e:
log.error(str(e))
# Delete the directories. First reverse-sort the normalized paths by
# length so that child directories are deleted before their parents.
dirs = [os.path.normpath(dir) for dir in dirs]
dirs.sort(key=len, reverse=True)
for dir in dirs:
try:
log.info("Removing the directory '%s'." % dir)
if not self.dry_run:
os.rmdir(dir)
except OSError, e:
if e.errno == errno.ENOTEMPTY:
log.info("Directory '%s' not empty; not removing." % dir)
else:
log.error(str(e))
distutils.core.setup(name=u"ndiff", scripts=[u"scripts/ndiff"], distutils.core.setup(name=u"ndiff", scripts=[u"scripts/ndiff"],
py_modules=[u"ndiff"], py_modules=[u"ndiff"],
data_files=[(u"share/man/man1", [u"docs/ndiff.1"])], data_files=[(u"share/man/man1", [u"docs/ndiff.1"])],
cmdclass={"install_egg_info": null_command, "install": checked_install}) cmdclass={
"install_egg_info": null_command,
"install": checked_install,
"uninstall": my_uninstall
})