Add PORTAGE_BINHOST sftp protocol support.
diff --git a/cnf/make.globals b/cnf/make.globals
index d14d051..9ba1044 100644
--- a/cnf/make.globals
+++ b/cnf/make.globals
@@ -46,6 +46,8 @@
 FETCHCOMMAND_SSH="bash -c \"x=\\\${2#ssh://} ; exec rsync -avP \\\"\\\${x%%/*}:/\\\${x#*/}\\\" \\\"\\\$1\\\"\" rsync \"\${DISTDIR}/\${FILE}\" \"\${URI}\""
 RESUMECOMMAND_SSH=${FETCHCOMMAND_SSH}
 
+FETCHCOMMAND_SFTP="bash -c \"x=\\\${2#sftp://} ; exec sftp \\\"\\\${x%%/*}:/\\\${x#*/}\\\" \\\"\\\$1\\\"\" sftp \"\${DISTDIR}/\${FILE}\" \"\${URI}\""
+
 # Default user options
 FEATURES="assume-digests binpkg-logs distlocks fixpackages
           fixlafiles news parallel-fetch protect-owned
diff --git a/pym/portage/dbapi/bintree.py b/pym/portage/dbapi/bintree.py
index f2a7cde..aec89e0 100644
--- a/pym/portage/dbapi/bintree.py
+++ b/pym/portage/dbapi/bintree.py
@@ -38,6 +38,7 @@
 import stat
 import subprocess
 import sys
+import tempfile
 import textwrap
 from itertools import chain
 try:
@@ -759,6 +760,7 @@
 			rmt_idx = self._new_pkgindex()
 			parsed_url = urlparse(base_url)
 			proc = None
+			tmp_filename = None
 			try:
 				# urlparse.urljoin() only works correctly with recognized
 				# protocols and requires the base url to have a trailing
@@ -766,12 +768,24 @@
 				try:
 					f = urllib_request_urlopen(base_url.rstrip("/") + "/Packages")
 				except IOError:
-					if parsed_url.scheme != 'ssh':
-						raise
 					path = parsed_url.path.rstrip("/") + "/Packages"
-					proc = subprocess.Popen(['ssh', parsed_url.netloc, '--',
-						'cat', path], stdout=subprocess.PIPE)
-					f = proc.stdout
+					if parsed_url.scheme == 'sftp':
+						# The sftp command complains about 'Illegal seek' if
+						# we try to make it write to /dev/stdout, so use a
+						# temp file instead.
+						fd, tmp_filename = tempfile.mkstemp()
+						os.close(fd)
+						proc = subprocess.Popen(['sftp',
+							parsed_url.netloc + ":" + path, tmp_filename])
+						if proc.wait() != os.EX_OK:
+							raise
+						f = open(tmp_filename, 'rb')
+					elif parsed_url.scheme == 'ssh':
+						proc = subprocess.Popen(['ssh', parsed_url.netloc, '--',
+							'cat', path], stdout=subprocess.PIPE)
+						f = proc.stdout
+					else:
+						raise
 
 				f_dec = codecs.iterdecode(f,
 					_encodings['repo.content'], errors='replace')
@@ -803,6 +817,11 @@
 					proc.kill()
 					proc.wait()
 				proc = None
+			if tmp_filename is not None:
+				try:
+					os.unlink(tmp_filename)
+				except OSError:
+					pass
 			if pkgindex is rmt_idx:
 				pkgindex.modified = False # don't update the header
 				try:
diff --git a/pym/portage/tests/util/test_getconfig.py b/pym/portage/tests/util/test_getconfig.py
index 5584db4..b1d3e25 100644
--- a/pym/portage/tests/util/test_getconfig.py
+++ b/pym/portage/tests/util/test_getconfig.py
@@ -15,6 +15,7 @@
 	_cases = {
 		'FETCHCOMMAND'             : '/usr/bin/wget -t 5 -T 60 --passive-ftp -O "${DISTDIR}/${FILE}" "${URI}"',
 		'FETCHCOMMAND_RSYNC'       : 'rsync -avP "${URI}" "${DISTDIR}/${FILE}"',
+		'FETCHCOMMAND_SFTP'        : 'bash -c "x=\\${2#sftp://} ; exec sftp \\"\\${x%%/*}:/\\${x#*/}\\" \\"\\$1\\"" sftp "${DISTDIR}/${FILE}" "${URI}"',
 		'FETCHCOMMAND_SSH'         : 'bash -c "x=\\${2#ssh://} ; exec rsync -avP \\"\\${x%%/*}:/\\${x#*/}\\" \\"\\$1\\"" rsync "${DISTDIR}/${FILE}" "${URI}"',
 		'PORTAGE_ELOG_MAILSUBJECT' : '[portage] ebuild log for ${PACKAGE} on ${HOST}'
 	}