--- a/src/modules/server/transaction.py Wed Mar 02 20:16:17 2016 -0800
+++ b/src/modules/server/transaction.py Sun Feb 28 16:24:18 2016 -0800
@@ -21,7 +21,7 @@
#
#
-# Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
#
from __future__ import print_function
@@ -483,9 +483,12 @@
digest.get_least_preferred_hash(action)
fname = hash_val
- # Extract ELF information
+ # Extract ELF information if not already provided.
# XXX This needs to be modularized.
- if haveelf and data[:4] == "\x7fELF":
+ if haveelf and data[:4] == "\x7fELF" and (
+ "elfarch" not in action.attrs or
+ "elfbits" not in action.attrs or
+ "elfhash" not in action.attrs):
elf_name = os.path.join(self.dir,
".temp-{0}".format(fname))
elf_file = open(elf_name, "wb")
--- a/src/publish.py Wed Mar 02 20:16:17 2016 -0800
+++ b/src/publish.py Sun Feb 28 16:24:18 2016 -0800
@@ -21,7 +21,7 @@
#
#
-# Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
#
from __future__ import print_function
@@ -52,6 +52,16 @@
nopub_actions = [ "unknown" ]
+# These attributes should always be stripped from input manifests for 'publish';
+# they will be re-calculated during publication.
+strip_attrs = [
+ "elfarch",
+ "elfbits",
+ "elfhash",
+ "pkg.csize",
+ "pkg.size",
+]
+
def error(text, cmd=None):
"""Emit an error message prefixed by the command name """
@@ -422,9 +432,10 @@
if a.name == "set" and a.attrs["name"] in ["pkg.fmri", "fmri"]:
continue
elif a.has_payload:
- # Don't trust values provided; forcibly discard these.
- a.attrs.pop("pkg.size", None)
- a.attrs.pop("pkg.csize", None)
+ # Forcibly discard content-related attributes to prevent
+ # errors when reusing manifests with different content.
+ for attr in strip_attrs:
+ a.attrs.pop(attr, None)
path = pkg.actions.set_action_data(a.hash, a,
basedirs=basedirs, bundles=bundles)[0]
elif a.name in nopub_actions:
--- a/src/tests/api/t_api_search.py Wed Mar 02 20:16:17 2016 -0800
+++ b/src/tests/api/t_api_search.py Sun Feb 28 16:24:18 2016 -0800
@@ -20,7 +20,7 @@
# CDDL HEADER END
#
-# Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
import testutils
if __name__ == "__main__":
@@ -47,6 +47,8 @@
class TestApiSearchBasics(pkg5unittest.SingleDepotTestCase):
+ # Tests in this suite use the read only data directory.
+ need_ro_data = True
example_pkg10 = """
open [email protected],5.11-0
@@ -382,7 +384,7 @@
add dir group=bin mode=0755 owner=root path=usr/share/info
add dir group=bin mode=0755 owner=root path=usr/share/man
add dir group=bin mode=0755 owner=root path=usr/share/man/man1
-add file tmp/example_file elfarch=i386 elfbits=32 elfhash=68cca393e816e6adcbac1e8ffe9c618de70413e0 group=bin mode=0555 owner=root path=usr/bin/gmake pkg.size=12
+add file ro_data/elftest.so.1 elfarch=i386 elfbits=32 elfhash=68cca393e816e6adcbac1e8ffe9c618de70413e0 group=bin mode=0555 owner=root path=usr/bin/gmake pkg.size=12
add file tmp/example_file group=bin mode=0444 owner=root path=usr/share/info/make.info pkg.size=12
add file tmp/example_file group=bin mode=0444 owner=root path=usr/share/info/make.info-1 pkg.size=12
add file tmp/example_file group=bin mode=0444 owner=root path=usr/share/info/make.info-2 pkg.size=12
@@ -398,7 +400,7 @@
res_bug_983 = set([
("pkg:/[email protected]", "basename", "link path=usr/sfw/bin/gmake target=../../bin/gmake"),
- ('pkg:/[email protected]', 'basename', 'file a686473102ba73bd7920fc0ab1d97e00a24ed704 chash=f88920ce1f61db185d127ccb32dc8cf401ae7a83 elfarch=i386 elfbits=32 elfhash=68cca393e816e6adcbac1e8ffe9c618de70413e0 group=bin mode=0555 owner=root path=usr/bin/gmake pkg.csize=30 pkg.size=12'),
+ ('pkg:/[email protected]', 'basename', 'file 038cc7a09940928aeac6966331a2f18bc40e7792 chash=a3e76bd1b97b715cddc93b2ad6502b41efa4d833 elfarch=i386 elfbits=32 elfhash=6975080bd79b8ccf8b6ba2e64a83ca67fac3e256 group=bin mode=0555 owner=root path=usr/bin/gmake pkg.csize=1358 pkg.size=3948'),
('pkg:/[email protected]', 'gmake - GNU make', 'set name=description value="gmake - GNU make"')
])
--- a/src/tests/cli/t_pkgrecv.py Wed Mar 02 20:16:17 2016 -0800
+++ b/src/tests/cli/t_pkgrecv.py Sun Feb 28 16:24:18 2016 -0800
@@ -21,7 +21,7 @@
#
#
-# Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
#
import testutils
@@ -49,6 +49,7 @@
import unittest
import zlib
+from pkg.actions import fromstr
from pkg.digest import DEFAULT_HASH_FUNC
from six.moves.urllib.parse import urlparse
from six.moves.urllib.request import url2pathname
@@ -62,6 +63,8 @@
class TestPkgrecvMulti(pkg5unittest.ManyDepotTestCase):
# Cleanup after every test.
persistent_setup = False
+ # Tests in this suite use the read only data directory.
+ need_ro_data = True
scheme10 = """
open pkg:/[email protected],5.11-0
@@ -160,6 +163,7 @@
add license tmp/copyright3 license=copyright
add file tmp/bronzeA2 mode=0444 owner=root group=bin path=/A1/B2/C3/D4/E5/F6/bronzeA2
add depend fmri=pkg:/[email protected] type=require
+ add file ro_data/elftest.so.1 mode=0755 owner=root group=bin path=bin/true
close
"""
@@ -1251,9 +1255,9 @@
self.pkgrecv(self.dpath1, "-d {0} -n -v \*".format(self.tempdir))
expected = """\
Retrieving packages (dry-run) ...
- Packages to add: 9
- Files to retrieve: 17
-Estimated transfer size: 528.00 B
+ Packages to add: 9
+ Files to retrieve: 19
+Estimated transfer size: 3.17 kB
"""
self.assert_(expected in self.output, self.output)
for s in self.published:
@@ -1267,9 +1271,9 @@
self.pkgrecv(self.dpath1, "-a -d {0} -n -v \*".format(self.tempdir))
expected = """\
Archiving packages (dry-run) ...
- Packages to add: 9
- Files to retrieve: 17
-Estimated transfer size: 528.00 B
+ Packages to add: 9
+ Files to retrieve: 19
+Estimated transfer size: 3.17 kB
"""
self.assert_(expected in self.output, self.output)
for s in self.published:
@@ -1282,9 +1286,9 @@
.format(self.tempdir))
expected = """\
Retrieving packages (dry-run) ...
- Packages to add: 9
- Files to retrieve: 17
-Estimated transfer size: 528.00 B
+ Packages to add: 9
+ Files to retrieve: 19
+Estimated transfer size: 3.17 kB
"""
self.assert_(expected in self.output, self.output)
for s in self.published:
@@ -1423,6 +1427,77 @@
self.pkgrepo("verify -s {0} --disable dependency"
.format(self.dpath6))
+ def test_15_content_attrs(self):
+ """Ensure that relevant content-related attributes will not be
+ modified by pkgrecv. This is important if changes are made to
+ how some attributes are calculated in the future and
+ modifications would invalidate signatures."""
+
+ #
+ # For now, this only needs to test 'elfhash'.
+ #
+ mfpath = os.path.join(self.test_root, "content-attrs.p5m")
+ with open(mfpath, "wb") as mf:
+ mf.write("""\
+set name=pkg.fmri value=pkg://test/[email protected]
+file elftest.so.1 mode=0755 owner=root group=bin path=bin/true
+""")
+
+ # Create a repository and publish sample package.
+ rpath = tempfile.mkdtemp(dir=self.test_root)
+ self.create_repo(rpath)
+ ret, pfmri = self.pkgsend(rpath,
+ "publish -d {0} {1}".format(self.ro_data_root, mfpath))
+ self.pkgrepo("list -s {0}".format(rpath))
+
+ # Now get the actual manifest and get current elfhash value.
+ orepo = repo.Repository(root=rpath)
+ rmpath = orepo.manifest(pfmri)
+ rm = manifest.Manifest()
+ rm.set_content(pathname=rmpath)
+ ract = list(rm.gen_actions_by_type('file'))[0]
+ oelfhash = ract.attrs["elfhash"]
+
+ # Create a new repository and pkgrecv package to that one so
+ # that we can safely modify it in place.
+ nrpath = tempfile.mkdtemp(dir=self.test_root)
+ self.create_repo(nrpath)
+ self.pkgrecv(rpath, "-d {0} \*".format(nrpath))
+ nrepo = repo.Repository(root=nrpath)
+ nmpath = nrepo.manifest(pfmri)
+ nm = manifest.Manifest()
+ nmcontent = rm.tostr_unsorted().replace(
+ "elfhash=", "elfhash=42.")
+ nm.set_content(nmcontent)
+ nm.store(nmpath)
+ # Modifying the manifest requires a catalog rebuild.
+ self.pkgrepo("rebuild --no-index -s {0}".format(nrpath))
+
+ # Now create another repository and pkgrecv package *without*
+ # using --clone to that one and verify that elfhash remains
+ # unchanged from previous repository version.
+ trpath = tempfile.mkdtemp(dir=self.test_root)
+ self.create_repo(trpath)
+ self.pkgrecv(nrpath, "-d {0} \*".format(trpath))
+ trepo = repo.Repository(root=trpath)
+ tmpath = trepo.manifest(pfmri)
+ tm = manifest.Manifest()
+ tm.set_content(pathname=tmpath)
+ tact = list(tm.gen_actions_by_type('file'))[0]
+ self.assertEqual("42." + oelfhash, tact.attrs["elfhash"])
+
+ # Do the same thing again, but use --clone this time.
+ trpath = tempfile.mkdtemp(dir=self.test_root)
+ self.create_repo(trpath)
+ self.pkgrecv(nrpath, "--clone -d {0} -p \*".format(trpath))
+ trepo = repo.Repository(root=trpath)
+ tmpath = trepo.manifest(pfmri)
+ tm = manifest.Manifest()
+ tm.set_content(pathname=tmpath)
+ tact = list(tm.gen_actions_by_type('file'))[0]
+ self.assertEqual("42." + oelfhash, tact.attrs["elfhash"])
+
+
class TestPkgrecvHTTPS(pkg5unittest.HTTPSTestClass):
example_pkg10 = """
--- a/src/tests/cli/t_pkgsend.py Wed Mar 02 20:16:17 2016 -0800
+++ b/src/tests/cli/t_pkgsend.py Sun Feb 28 16:24:18 2016 -0800
@@ -20,7 +20,7 @@
# CDDL HEADER END
#
-# Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
import testutils
if __name__ == "__main__":
@@ -36,6 +36,7 @@
import stat
import tempfile
import unittest
+import six
from six.moves import range
from six.moves.urllib.error import HTTPError
from six.moves.urllib.request import urlopen, Request, pathname2url
@@ -54,6 +55,8 @@
class TestPkgsendBasics(pkg5unittest.SingleDepotTestCase):
persistent_setup = False
+ # Tests in this suite use the read only data directory.
+ need_ro_data = True
def setUp(self):
# This test suite needs an actual depot.
@@ -1406,6 +1409,53 @@
self.assertEqualDiff(self.reduceSpaces(expected),
self.reduceSpaces(actual))
+ def test_28_content_attrs(self):
+ """Ensure that content-related attributes are ignored for
+ 'pgksend publish'."""
+
+ mfpath = os.path.join(self.test_root, "content-attrs.p5m")
+ with open(mfpath, "wb") as mf:
+ mf.write("""\
+set name=pkg.fmri value=pkg://test/[email protected]
+file elftest.so.1 mode=0755 owner=root group=bin path=bin/true pkg.size=ignored pkg.csize=ignored elfhash=ignored elfbits=ignored elfarch=ignored
+""")
+
+ # Verify pkgsend publish can be performed even though values for
+ # content-related attributes are invalid. They should be
+ # forcibly dropped and added back.
+ ret, pfmri = self.pkgsend(self.dc.get_depot_url(),
+ "publish -d {0} {1}".format(self.ro_data_root, mfpath))
+
+ # Now get the actual manifest and ensure all attributes were
+ # overwritten.
+ repo = self.dc.get_repo()
+ rmpath = repo.manifest(pfmri)
+ rm = manifest.Manifest()
+ rm.set_content(pathname=rmpath)
+ a = list(rm.gen_actions_by_type('file'))[0]
+
+ # These attributes should always match pre-determined values.
+ expected = {
+ 'elfarch': 'i386',
+ 'elfbits': '32',
+ 'group': 'bin',
+ 'mode': '0755',
+ 'owner': 'root',
+ 'path': 'bin/true',
+ 'pkg.csize': '1358',
+ 'pkg.size': '3948'
+ }
+ actual = dict(
+ (k, v) for (k, v) in six.iteritems(a.attrs)
+ if k in expected
+ )
+ self.assertEqualDiff(expected, actual)
+
+ # 'elfhash' can vary depending upon whether we've changed the
+ # content-hashing algorithms, so we only verify it exists and
+ # doesn't have a value of 'ignored'.
+ self.assertNotEqual(a.attrs['elfhash'], 'ignored')
+
class TestPkgsendHardlinks(pkg5unittest.CliTestCase):