diff options
Diffstat (limited to 'meta/classes/sstate.bbclass')
| -rw-r--r-- | meta/classes/sstate.bbclass | 105 |
1 files changed, 97 insertions, 8 deletions
diff --git a/meta/classes/sstate.bbclass b/meta/classes/sstate.bbclass index 59ebc3ab5c..da0807d6e9 100644 --- a/meta/classes/sstate.bbclass +++ b/meta/classes/sstate.bbclass | |||
| @@ -11,7 +11,7 @@ def generate_sstatefn(spec, hash, d): | |||
| 11 | SSTATE_PKGARCH = "${PACKAGE_ARCH}" | 11 | SSTATE_PKGARCH = "${PACKAGE_ARCH}" |
| 12 | SSTATE_PKGSPEC = "sstate:${PN}:${PACKAGE_ARCH}${TARGET_VENDOR}-${TARGET_OS}:${PV}:${PR}:${SSTATE_PKGARCH}:${SSTATE_VERSION}:" | 12 | SSTATE_PKGSPEC = "sstate:${PN}:${PACKAGE_ARCH}${TARGET_VENDOR}-${TARGET_OS}:${PV}:${PR}:${SSTATE_PKGARCH}:${SSTATE_VERSION}:" |
| 13 | SSTATE_SWSPEC = "sstate:${PN}::${PV}:${PR}::${SSTATE_VERSION}:" | 13 | SSTATE_SWSPEC = "sstate:${PN}::${PV}:${PR}::${SSTATE_VERSION}:" |
| 14 | SSTATE_PKGNAME = "${SSTATE_EXTRAPATH}${@generate_sstatefn(d.getVar('SSTATE_PKGSPEC'), d.getVar('BB_TASKHASH'), d)}" | 14 | SSTATE_PKGNAME = "${SSTATE_EXTRAPATH}${@generate_sstatefn(d.getVar('SSTATE_PKGSPEC'), d.getVar('BB_UNIHASH'), d)}" |
| 15 | SSTATE_PKG = "${SSTATE_DIR}/${SSTATE_PKGNAME}" | 15 | SSTATE_PKG = "${SSTATE_DIR}/${SSTATE_PKGNAME}" |
| 16 | SSTATE_EXTRAPATH = "" | 16 | SSTATE_EXTRAPATH = "" |
| 17 | SSTATE_EXTRAPATHWILDCARD = "" | 17 | SSTATE_EXTRAPATHWILDCARD = "" |
| @@ -82,6 +82,23 @@ SSTATE_SIG_PASSPHRASE ?= "" | |||
| 82 | # Whether to verify the GnUPG signatures when extracting sstate archives | 82 | # Whether to verify the GnUPG signatures when extracting sstate archives |
| 83 | SSTATE_VERIFY_SIG ?= "0" | 83 | SSTATE_VERIFY_SIG ?= "0" |
| 84 | 84 | ||
| 85 | SSTATE_HASHEQUIV_METHOD ?= "OEOuthashBasic" | ||
| 86 | SSTATE_HASHEQUIV_METHOD[doc] = "The function used to calculate the output hash \ | ||
| 87 | for a task, which in turn is used to determine equivalency. \ | ||
| 88 | " | ||
| 89 | |||
| 90 | SSTATE_HASHEQUIV_SERVER ?= "" | ||
| 91 | SSTATE_HASHEQUIV_SERVER[doc] = "The hash equivalence sever. For example, \ | ||
| 92 | 'http://192.168.0.1:5000'. Do not include a trailing slash \ | ||
| 93 | " | ||
| 94 | |||
| 95 | SSTATE_HASHEQUIV_REPORT_TASKDATA ?= "0" | ||
| 96 | SSTATE_HASHEQUIV_REPORT_TASKDATA[doc] = "Report additional useful data to the \ | ||
| 97 | hash equivalency server, such as PN, PV, taskname, etc. This information \ | ||
| 98 | is very useful for developers looking at task data, but may leak sensitive \ | ||
| 99 | data if the equivalence server is public. \ | ||
| 100 | " | ||
| 101 | |||
| 85 | python () { | 102 | python () { |
| 86 | if bb.data.inherits_class('native', d): | 103 | if bb.data.inherits_class('native', d): |
| 87 | d.setVar('SSTATE_PKGARCH', d.getVar('BUILD_ARCH', False)) | 104 | d.setVar('SSTATE_PKGARCH', d.getVar('BUILD_ARCH', False)) |
| @@ -640,7 +657,7 @@ def sstate_package(ss, d): | |||
| 640 | return | 657 | return |
| 641 | 658 | ||
| 642 | for f in (d.getVar('SSTATECREATEFUNCS') or '').split() + \ | 659 | for f in (d.getVar('SSTATECREATEFUNCS') or '').split() + \ |
| 643 | ['sstate_create_package', 'sstate_sign_package'] + \ | 660 | ['sstate_report_unihash', 'sstate_create_package', 'sstate_sign_package'] + \ |
| 644 | (d.getVar('SSTATEPOSTCREATEFUNCS') or '').split(): | 661 | (d.getVar('SSTATEPOSTCREATEFUNCS') or '').split(): |
| 645 | # All hooks should run in SSTATE_BUILDDIR. | 662 | # All hooks should run in SSTATE_BUILDDIR. |
| 646 | bb.build.exec_func(f, d, (sstatebuild,)) | 663 | bb.build.exec_func(f, d, (sstatebuild,)) |
| @@ -764,6 +781,73 @@ python sstate_sign_package () { | |||
| 764 | d.getVar('SSTATE_SIG_PASSPHRASE'), armor=False) | 781 | d.getVar('SSTATE_SIG_PASSPHRASE'), armor=False) |
| 765 | } | 782 | } |
| 766 | 783 | ||
| 784 | def OEOuthashBasic(path, sigfile, task, d): | ||
| 785 | import hashlib | ||
| 786 | import stat | ||
| 787 | |||
| 788 | def update_hash(s): | ||
| 789 | s = s.encode('utf-8') | ||
| 790 | h.update(s) | ||
| 791 | if sigfile: | ||
| 792 | sigfile.write(s) | ||
| 793 | |||
| 794 | h = hashlib.sha256() | ||
| 795 | prev_dir = os.getcwd() | ||
| 796 | |||
| 797 | try: | ||
| 798 | os.chdir(path) | ||
| 799 | |||
| 800 | update_hash("OEOuthashBasic\n") | ||
| 801 | |||
| 802 | # It is only currently useful to get equivalent hashes for things that | ||
| 803 | # can be restored from sstate. Since the sstate object is named using | ||
| 804 | # SSTATE_PKGSPEC and the task name, those should be included in the | ||
| 805 | # output hash calculation. | ||
| 806 | update_hash("SSTATE_PKGSPEC=%s\n" % d.getVar('SSTATE_PKGSPEC')) | ||
| 807 | update_hash("task=%s\n" % task) | ||
| 808 | |||
| 809 | for root, dirs, files in os.walk('.', topdown=True): | ||
| 810 | # Sort directories and files to ensure consistent ordering | ||
| 811 | dirs.sort() | ||
| 812 | files.sort() | ||
| 813 | |||
| 814 | for f in files: | ||
| 815 | path = os.path.join(root, f) | ||
| 816 | s = os.lstat(path) | ||
| 817 | |||
| 818 | # Hash file path | ||
| 819 | update_hash(path + '\n') | ||
| 820 | |||
| 821 | # Hash file mode | ||
| 822 | update_hash("\tmode=0x%x\n" % stat.S_IMODE(s.st_mode)) | ||
| 823 | update_hash("\ttype=0x%x\n" % stat.S_IFMT(s.st_mode)) | ||
| 824 | |||
| 825 | if stat.S_ISBLK(s.st_mode) or stat.S_ISBLK(s.st_mode): | ||
| 826 | # Hash device major and minor | ||
| 827 | update_hash("\tdev=%d,%d\n" % (os.major(s.st_rdev), os.minor(s.st_rdev))) | ||
| 828 | elif stat.S_ISLNK(s.st_mode): | ||
| 829 | # Hash symbolic link | ||
| 830 | update_hash("\tsymlink=%s\n" % os.readlink(path)) | ||
| 831 | else: | ||
| 832 | fh = hashlib.sha256() | ||
| 833 | # Hash file contents | ||
| 834 | with open(path, 'rb') as d: | ||
| 835 | for chunk in iter(lambda: d.read(4096), b""): | ||
| 836 | fh.update(chunk) | ||
| 837 | update_hash("\tdigest=%s\n" % fh.hexdigest()) | ||
| 838 | finally: | ||
| 839 | os.chdir(prev_dir) | ||
| 840 | |||
| 841 | return h.hexdigest() | ||
| 842 | |||
| 843 | python sstate_report_unihash() { | ||
| 844 | report_unihash = getattr(bb.parse.siggen, 'report_unihash', None) | ||
| 845 | |||
| 846 | if report_unihash: | ||
| 847 | ss = sstate_state_fromvars(d) | ||
| 848 | report_unihash(os.getcwd(), ss['task'], d) | ||
| 849 | } | ||
| 850 | |||
| 767 | # | 851 | # |
| 768 | # Shell function to decompress and prepare a package for installation | 852 | # Shell function to decompress and prepare a package for installation |
| 769 | # Will be run from within SSTATE_INSTDIR. | 853 | # Will be run from within SSTATE_INSTDIR. |
| @@ -788,6 +872,11 @@ def sstate_checkhashes(sq_fn, sq_task, sq_hash, sq_hashfn, d, siginfo=False, *, | |||
| 788 | if siginfo: | 872 | if siginfo: |
| 789 | extension = extension + ".siginfo" | 873 | extension = extension + ".siginfo" |
| 790 | 874 | ||
| 875 | def gethash(task): | ||
| 876 | if sq_unihash is not None: | ||
| 877 | return sq_unihash[task] | ||
| 878 | return sq_hash[task] | ||
| 879 | |||
| 791 | def getpathcomponents(task, d): | 880 | def getpathcomponents(task, d): |
| 792 | # Magic data from BB_HASHFILENAME | 881 | # Magic data from BB_HASHFILENAME |
| 793 | splithashfn = sq_hashfn[task].split(" ") | 882 | splithashfn = sq_hashfn[task].split(" ") |
| @@ -810,7 +899,7 @@ def sstate_checkhashes(sq_fn, sq_task, sq_hash, sq_hashfn, d, siginfo=False, *, | |||
| 810 | 899 | ||
| 811 | spec, extrapath, tname = getpathcomponents(task, d) | 900 | spec, extrapath, tname = getpathcomponents(task, d) |
| 812 | 901 | ||
| 813 | sstatefile = d.expand("${SSTATE_DIR}/" + extrapath + generate_sstatefn(spec, sq_hash[task], d) + "_" + tname + extension) | 902 | sstatefile = d.expand("${SSTATE_DIR}/" + extrapath + generate_sstatefn(spec, gethash(task), d) + "_" + tname + extension) |
| 814 | 903 | ||
| 815 | if os.path.exists(sstatefile): | 904 | if os.path.exists(sstatefile): |
| 816 | bb.debug(2, "SState: Found valid sstate file %s" % sstatefile) | 905 | bb.debug(2, "SState: Found valid sstate file %s" % sstatefile) |
| @@ -872,7 +961,7 @@ def sstate_checkhashes(sq_fn, sq_task, sq_hash, sq_hashfn, d, siginfo=False, *, | |||
| 872 | if task in ret: | 961 | if task in ret: |
| 873 | continue | 962 | continue |
| 874 | spec, extrapath, tname = getpathcomponents(task, d) | 963 | spec, extrapath, tname = getpathcomponents(task, d) |
| 875 | sstatefile = d.expand(extrapath + generate_sstatefn(spec, sq_hash[task], d) + "_" + tname + extension) | 964 | sstatefile = d.expand(extrapath + generate_sstatefn(spec, gethash(task), d) + "_" + tname + extension) |
| 876 | tasklist.append((task, sstatefile)) | 965 | tasklist.append((task, sstatefile)) |
| 877 | 966 | ||
| 878 | if tasklist: | 967 | if tasklist: |
| @@ -898,12 +987,12 @@ def sstate_checkhashes(sq_fn, sq_task, sq_hash, sq_hashfn, d, siginfo=False, *, | |||
| 898 | evdata = {'missed': [], 'found': []}; | 987 | evdata = {'missed': [], 'found': []}; |
| 899 | for task in missed: | 988 | for task in missed: |
| 900 | spec, extrapath, tname = getpathcomponents(task, d) | 989 | spec, extrapath, tname = getpathcomponents(task, d) |
| 901 | sstatefile = d.expand(extrapath + generate_sstatefn(spec, sq_hash[task], d) + "_" + tname + ".tgz") | 990 | sstatefile = d.expand(extrapath + generate_sstatefn(spec, gethash(task), d) + "_" + tname + ".tgz") |
| 902 | evdata['missed'].append( (sq_fn[task], sq_task[task], sq_hash[task], sstatefile ) ) | 991 | evdata['missed'].append( (sq_fn[task], sq_task[task], gethash(task), sstatefile ) ) |
| 903 | for task in ret: | 992 | for task in ret: |
| 904 | spec, extrapath, tname = getpathcomponents(task, d) | 993 | spec, extrapath, tname = getpathcomponents(task, d) |
| 905 | sstatefile = d.expand(extrapath + generate_sstatefn(spec, sq_hash[task], d) + "_" + tname + ".tgz") | 994 | sstatefile = d.expand(extrapath + generate_sstatefn(spec, gethash(task), d) + "_" + tname + ".tgz") |
| 906 | evdata['found'].append( (sq_fn[task], sq_task[task], sq_hash[task], sstatefile ) ) | 995 | evdata['found'].append( (sq_fn[task], sq_task[task], gethash(task), sstatefile ) ) |
| 907 | bb.event.fire(bb.event.MetadataEvent("MissedSstate", evdata), d) | 996 | bb.event.fire(bb.event.MetadataEvent("MissedSstate", evdata), d) |
| 908 | 997 | ||
| 909 | # Print some summary statistics about the current task completion and how much sstate | 998 | # Print some summary statistics about the current task completion and how much sstate |
