From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by mail.openembedded.org (Postfix) with ESMTP id C5F08782CA for ; Wed, 14 Jun 2017 20:50:52 +0000 (UTC) Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by orsmga102.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 14 Jun 2017 13:50:34 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.39,341,1493708400"; d="scan'208,217";a="868035044" Received: from orsmsx107.amr.corp.intel.com ([10.22.240.5]) by FMSMGA003.fm.intel.com with ESMTP; 14 Jun 2017 13:50:33 -0700 Received: from orsmsx112.amr.corp.intel.com ([169.254.3.182]) by ORSMSX107.amr.corp.intel.com ([169.254.1.201]) with mapi id 14.03.0319.002; Wed, 14 Jun 2017 13:50:32 -0700 From: "Bystricky, Juro" To: Martin Jansa Thread-Topic: [PATCH v2 2/6] base.bbclass: initial support for binary reproducibility Thread-Index: AQHSwr3HMJQCx56iAk+9CAhEfeqxG6IlihyA//+N9sA= Date: Wed, 14 Jun 2017 20:50:31 +0000 Message-ID: <6E51916E4A1F32428260031F4C7CD2B61198C2F5@ORSMSX112.amr.corp.intel.com> References: <1493672344-21965-1-git-send-email-juro.bystricky@intel.com> <1493672344-21965-3-git-send-email-juro.bystricky@intel.com>, In-Reply-To: Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.19.9.46] MIME-Version: 1.0 Cc: Patches and discussions about the oe-core layer , Juro Bystricky Subject: Re: [PATCH v2 2/6] base.bbclass: initial support for binary reproducibility X-BeenThere: openembedded-core@lists.openembedded.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: Patches and discussions about the oe-core layer List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 14 Jun 2017 20:50:53 -0000 Content-Language: en-US Content-Type: multipart/alternative; boundary="_000_6E51916E4A1F32428260031F4C7CD2B61198C2F5ORSMSX112amrcor_" --_000_6E51916E4A1F32428260031F4C7CD2B61198C2F5ORSMSX112amrcor_ Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Thanks, it seems there is not-too-great error checking implemented. There i= s an assumption if there is a git folder there is also a git repo (and "git" binary in PATH). Seems the= assumption is wrong. I'll add some error checking/improved error message. The problem with git r= epos is they modify the file mod timestamps upon checkout, so it is not possible to find the one th= at is truly the youngest. So the code tries to get the timestamp of the top commit instead. ________________________________ From: Martin Jansa [martin.jansa@gmail.com] Sent: Wednesday, June 14, 2017 1:30 PM To: Bystricky, Juro Cc: Patches and discussions about the oe-core layer; Richard Purdie; Joshua= G Lock; Burton, Ross; Khem Raj; Juro Bystricky Subject: Re: [PATCH v2 2/6] base.bbclass: initial support for binary reprod= ucibility For some recipes (llvm, chromium, chromium-wayland) I've noticed this funct= ion to fail with: ERROR: llvm3.3-3.3-r0 do_unpack: Error executing a python function in exec_= python_func() autogenerated: The stack trace of python calls that resulted in this exception/failure was= : File: 'exec_python_func() autogenerated', lineno: 2, function: 0001: *** 0002:base_do_unpack(d) 0003: File: '/home/jenkins/oe/world/shr-core/openembedded-core/meta/classes/base.= bbclass', lineno: 215, function: base_do_unpack 0211: 0212: try: 0213: fetcher =3D bb.fetch2.Fetch(src_uri, d) 0214: fetcher.unpack(d.getVar('WORKDIR')) *** 0215: create_src_date_epoch_stamp(d) 0216: except bb.fetch2.BBFetchException as e: 0217: bb.fatal(str(e)) 0218:} 0219: File: '/home/jenkins/oe/world/shr-core/openembedded-core/meta/classes/base.= bbclass', lineno: 34, function: create_src_date_epoch_stamp 0030: exclude =3D set(["temp", "licenses", "patches", "reci= pe-sysroot-native", "recipe-sysroot" ]) 0031: for root, dirs, files in os.walk(path, topdown=3DTrue= ): 0032: dirs[:] =3D [d for d in dirs if d not in exclude] 0033: if root.endswith('/git'): *** 0034: src_date_epoch =3D get_git_src_date_epoch(d, = root) 0035: break 0036: 0037: for fname in files: 0038: filename =3D os.path.join(root, fname) File: '/home/jenkins/oe/world/shr-core/openembedded-core/meta/classes/base.= bbclass', lineno: 17, function: get_git_src_date_epoch 0013:def get_git_src_date_epoch(d, path): 0014: import subprocess 0015: saved_cwd =3D os.getcwd() 0016: os.chdir(path) *** 0017: src_date_epoch =3D int(subprocess.check_output(['git','log','= -1','--pretty=3D%ct'])) 0018: os.chdir(saved_cwd) 0019: return src_date_epoch 0020: 0021:def create_src_date_epoch_stamp(d): File: '/usr/lib/python3.5/subprocess.py', lineno: 626, function: check_outp= ut 0622: # empty string. That is maintained here for backwards com= patibility. 0623: kwargs['input'] =3D '' if kwargs.get('universal_newlines'= , False) else b'' 0624: 0625: return run(*popenargs, stdout=3DPIPE, timeout=3Dtimeout, chec= k=3DTrue, *** 0626: **kwargs).stdout 0627: 0628: 0629:class CompletedProcess(object): 0630: """A process that has finished running. File: '/usr/lib/python3.5/subprocess.py', lineno: 708, function: run 0704: raise 0705: retcode =3D process.poll() 0706: if check and retcode: 0707: raise CalledProcessError(retcode, process.args, *** 0708: output=3Dstdout, stderr=3Dst= derr) 0709: return CompletedProcess(process.args, retcode, stdout, stderr= ) 0710: 0711: 0712:def list2cmdline(seq): Exception: subprocess.CalledProcessError: Command '['git', 'log', '-1', '--= pretty=3D%ct']' returned non-zero exit status 128 ERROR: llvm3.3-3.3-r0 do_unpack: Function failed: base_do_unpack ERROR: Logfile of failure stored in: /home/jenkins/oe/world/shr-core/tmp-gl= ibc/work/i586-oe-linux/llvm3.3/3.3-r0/temp/log.do_unpack.25005 NOTE: recipe llvm3.3-3.3-r0: task do_unpack: Failed ERROR: Task (/home/jenkins/oe/world/shr-core/meta-openembedded/meta-oe/reci= pes-core/llvm/llvm3.3_3.3.bb:do_unpack) failed with exit code '1' Maybe I don't have the latest version of this patch (I'm not using your pok= y-contrib branch yet), but it should fail with nicer message when git log f= ails for whatever reason. On Mon, May 1, 2017 at 10:59 PM, Juro Bystricky > wrote: Conditionally set some environment variables in order to achieve improved binary reproducibility. Providing BUILD_REPRODUCIBLE_BINARIES is set to "1", we set the following environment variables: export PYTHONHASHSEED=3D0 export PERL_HASH_SEED=3D0 export TZ=3D"UTC" We also export and set SOURCE_DATE_EPOCH. The value for this variable is obtained after source code for a recipe has been unpacked, but before it= is patched. If the code comes from a GIT repo, we get the timestamp from the t= op commit. (This usually corresponds to the mktime of "changelog".) Otherwise we go through all files and get the timestamp from the youngest one. We create a timestamp for each recipe. The timestamp is stored in the = file 'src_date_epoch.txt'. Later on, each task reads this file and sets SOURCE_D= ATE_EPOCH based on the value found in the file. [YOCTO#11178] [YOCTO#11179] Signed-off-by: Juro Bystricky > --- meta/classes/base.bbclass | 82 +++++++++++++++++++++++++++++++++++++++++++= ++++ 1 file changed, 82 insertions(+) diff --git a/meta/classes/base.bbclass b/meta/classes/base.bbclass index e29821f..f2b2d97 100644 --- a/meta/classes/base.bbclass +++ b/meta/classes/base.bbclass @@ -10,6 +10,52 @@ inherit utility-tasks inherit metadata_scm inherit logging +def get_git_src_date_epoch(d, path): + import subprocess + saved_cwd =3D os.getcwd() + os.chdir(path) + src_date_epoch =3D int(subprocess.check_output(['git','log','-1','--pr= etty=3D%ct'])) + os.chdir(saved_cwd) + return src_date_epoch + +def create_src_date_epoch_stamp(d): + if d.getVar('BUILD_REPRODUCIBLE_BINARIES') =3D=3D '1': + path =3D d.getVar('S') + src_date_epoch =3D 0 + filename_dbg =3D None + + if path.endswith('/git'): + src_date_epoch =3D get_git_src_date_epoch(d, path) + else: + exclude =3D set(["temp", "licenses", "patches", "recipe-sysroo= t-native", "recipe-sysroot" ]) + for root, dirs, files in os.walk(path, topdown=3DTrue): + dirs[:] =3D [d for d in dirs if d not in exclude] + if root.endswith('/git'): + src_date_epoch =3D get_git_src_date_epoch(d, root) + break + + for fname in files: + filename =3D os.path.join(root, fname) + try: + mtime =3D int(os.path.getmtime(filename)) + except: + mtime =3D 0 + if mtime > src_date_epoch: + src_date_epoch =3D mtime + filename_dbg =3D filename + + # Most likely an empty folder + if src_date_epoch =3D=3D 0: + bb.warn("Unable to determine src_date_epoch! path:%s" % path) + + f =3D open(os.path.join(path,'src_date_epoch.txt'), 'w') + f.write(str(src_date_epoch)) + f.close() + + if filename_dbg !=3D None: + bb.debug(1," src_date_epoch %d derived from: %s" % (src_date_e= poch, filename_dbg)) + + OE_IMPORTS +=3D "os sys time oe.path oe.utils oe.types oe.package oe.packa= gegroup oe.sstatesig oe.lsb oe.cachedpath oe.license" OE_IMPORTS[type] =3D "list" @@ -173,6 +219,7 @@ python base_do_unpack() { try: fetcher =3D bb.fetch2.Fetch(src_uri, d) fetcher.unpack(d.getVar('WORKDIR')) + create_src_date_epoch_stamp(d) except bb.fetch2.BBFetchException as e: bb.fatal(str(e)) } @@ -383,9 +430,43 @@ def set_packagetriplet(d): settriplet(d, "PKGMLTRIPLETS", archs, tos, tvs) + +export PYTHONHASHSEED +export PERL_HASH_SEED +export SOURCE_DATE_EPOCH + +BB_HASHBASE_WHITELIST +=3D "SOURCE_DATE_EPOCH PYTHONHASHSEED PERL_HASH_SEE= D " + python () { import string, re + # Create reproducible_environment + + if d.getVar('BUILD_REPRODUCIBLE_BINARIES') =3D=3D '1': + import subprocess + d.setVar('PYTHONHASHSEED', '0') + d.setVar('PERL_HASH_SEED', '0') + d.setVar('TZ', 'UTC') + + path =3D d.getVar('S') + epochfile =3D os.path.join(path,'src_date_epoch.txt') + if os.path.isfile(epochfile): + f =3D open(epochfile, 'r') + src_date_epoch =3D f.read() + f.close() + bb.debug(1, "src_date_epoch stamp found ---> stamp %s" % src_d= ate_epoch) + d.setVar('SOURCE_DATE_EPOCH', src_date_epoch) + else: + bb.debug(1, "src_date_epoch stamp not found.") + d.setVar('SOURCE_DATE_EPOCH', '0') + else: + if 'PYTHONHASHSEED' in os.environ: + del os.environ['PYTHONHASHSEED'] + if 'PERL_HASH_SEED' in os.environ: + del os.environ['PERL_HASH_SEED'] + if 'SOURCE_DATE_EPOCH' in os.environ: + del os.environ['SOURCE_DATE_EPOCH'] + # Handle PACKAGECONFIG # # These take the form: @@ -678,6 +759,7 @@ python () { bb.warn("Recipe %s is marked as only being architecture specif= ic but seems to have machine specific packages?! The recipe may as well mar= k itself as machine specific directly." % d.getVar("PN")) } + addtask cleansstate after do_clean python do_cleansstate() { sstate_clean_cachefiles(d) -- 2.7.4 --_000_6E51916E4A1F32428260031F4C7CD2B61198C2F5ORSMSX112amrcor_ Content-Type: text/html; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable
Thanks, it seems there is not-too-great error checking implemented. = There is an assumption if there is
a git folder there is also a git repo (and "git" binary in PATH).= Seems the assumption is wrong.
I'll add some error checking/improved error message. The problem with git r= epos is they modify the
file mod timestamps upon checkout, so it is not possible to find the one th= at is truly the youngest.
So the code tries to get the timestamp of the top commit instead.

From: Martin Jansa [martin.jansa@gmail.= com]
Sent: Wednesday, June 14, 2017 1:30 PM
To: Bystricky, Juro
Cc: Patches and discussions about the oe-core layer; Richard Purdie;= Joshua G Lock; Burton, Ross; Khem Raj; Juro Bystricky
Subject: Re: [PATCH v2 2/6] base.bbclass: initial support for binary= reproducibility

For some recipes (llvm, chromium, chromium-wayland) I've n= oticed this function to fail with:

ERROR: llvm3.3-3.3-r=
0 do_unpack: Error executing a python function in exec_python_func() autoge=
nerated:=0A=
=0A=
The stack trace of python calls that resulted in this exception/failure was=
:=0A=
File: 'exec_python_func() autogenerated', lineno: 2, function: <module&g=
t;=0A=
     0001:=0A=
 *** 0002:base_do_unpack(d)=0A=
     0003:=0A=
File: '/home/jenkins/oe/world/shr-core/openembedded-core/meta/classes/base.=
bbclass', lineno: 215, function: base_do_unpack=0A=
     0211:=0A=
     0212:    try:=0A=
     0213:        fetcher =3D bb.fetch2.Fetch(src_uri, d)=0A=
     0214:        fetcher.unpack(d.getVar('WORKDIR'))=0A=
 *** 0215:        create_src_date_epoch_stamp(d)=0A=
     0216:    except bb.fetch2.BBFetchException as e:=0A=
     0217:        bb.fatal(str(e))=0A=
     0218:}=0A=
     0219:=0A=
File: '/home/jenkins/oe/world/shr-core/openembedded-core/meta/classes/base.=
bbclass', lineno: 34, function: create_src_date_epoch_stamp=0A=
     0030:            exclude =3D set(["temp", "licenses&quo=
t;, "patches", "recipe-sysroot-native", "recipe-sy=
sroot" ])=0A=
     0031:            for root, dirs, files in os.walk(path, topdown=3DTrue=
):=0A=
     0032:                dirs[:] =3D [d for d in dirs if d not in exclude]=
=0A=
     0033:                if root.endswith('/git'):=0A=
 *** 0034:                    src_date_epoch =3D get_git_src_date_epoch(d, =
root)=0A=
     0035:                    break=0A=
     0036:=0A=
     0037:                for fname in files:=0A=
     0038:                    filename =3D os.path.join(root, fname)=0A=
File: '/home/jenkins/oe/world/shr-core/openembedded-core/meta/classes/base.=
bbclass', lineno: 17, function: get_git_src_date_epoch=0A=
     0013:def get_git_src_date_epoch(d, path):=0A=
     0014:    import subprocess=0A=
     0015:    saved_cwd =3D os.getcwd()=0A=
     0016:    os.chdir(path)=0A=
 *** 0017:    src_date_epoch =3D int(subprocess.check_output(['git','log','=
-1','--pretty=3D%ct']))=0A=
     0018:    os.chdir(saved_cwd)=0A=
     0019:    return src_date_epoch=0A=
     0020:=0A=
     0021:def create_src_date_epoch_stamp(d):=0A=
File: '/usr/lib/python3.5/subprocess.py', lineno: 626, function: check_outp=
ut=0A=
     0622:        # empty string. That is maintained here for backwards com=
patibility.=0A=
     0623:        kwargs['input'] =3D '' if kwargs.get('universal_newlines'=
, False) else b''=0A=
     0624:=0A=
     0625:    return run(*popenargs, stdout=3DPIPE, timeout=3Dtimeout, chec=
k=3DTrue,=0A=
 *** 0626:               **kwargs).stdout=0A=
     0627:=0A=
     0628:=0A=
     0629:class CompletedProcess(object):=0A=
     0630:    """A process that has finished running.=0A=
File: '/usr/lib/python3.5/subprocess.py', lineno: 708, function: run=0A=
     0704:            raise=0A=
     0705:        retcode =3D process.poll()=0A=
     0706:        if check and retcode:=0A=
     0707:            raise CalledProcessError(retcode, process.args,=0A=
 *** 0708:                                     output=3Dstdout, stderr=3Dst=
derr)=0A=
     0709:    return CompletedProcess(process.args, retcode, stdout, stderr=
)=0A=
     0710:=0A=
     0711:=0A=
     0712:def list2cmdline(seq):=0A=
Exception: subprocess.CalledProcessError: Command '['git', 'log', '-1', '--=
pretty=3D%ct']' returned non-zero exit status 128=0A=
=0A=
ERROR: llvm3.3-3.3-r0 do_unpack: Function failed: base_do_unpack=0A=
ERROR: Logfile of failure stored in: /home/jenkins/oe/world/shr-core/tmp-gl=
ibc/work/i586-oe-linux/llvm3.3/3.3-r0/temp/log.do_unpack.25005=0A=
NOTE: recipe llvm3.3-3.3-r0: task do_unpack: Failed=0A=
ERROR: Task (/home/jenkins/oe/world/shr-core/meta-openembedded/meta-oe/reci=
pes-core/llvm/llvm3.3_3.3.bb:do_unpack) failed with exit code '1'

Maybe I don't have t=
he latest version of this patch (I'm not using your poky-contrib branch yet=
), but it should fail with nicer message when git log fails for whatever re=
ason.

On Mon, May 1, 2017 at 10:59 PM, Juro Bystricky = <juro.byst= ricky@intel.com> wrote:
Conditionally set some environment variables in order to achieve
improved binary reproducibility. Providing BUILD_REPRODUCIBLE_BINARIES is set to "1", we set the following environment variables:

export PYTHONHASHSEED=3D0
export PERL_HASH_SEED=3D0
export TZ=3D"UTC"

We also export and set SOURCE_DATE_EPOCH. The value for this variable
is obtained after source code for a recipe has been unpacked, but before it= is
patched. If the code comes from a GIT repo, we get the timestamp from the t= op
commit. (This usually corresponds to the mktime of "changelog".)<= br> Otherwise we go through all files and get the timestamp from the youngest one. We create a timestamp for each recipe. The timestamp is stored in the = file
'src_date_epoch.txt'. Later on, each task reads this file and sets SOURCE_D= ATE_EPOCH
based on the value found in the file.

[YOCTO#11178]
[YOCTO#11179]

Signed-off-by: Juro Bystricky <juro.bystricky@intel.com>
---
 meta/classes/base.bbclass | 82 +++++++= 3;++++++++++++++= 3;+++++++++++++= 3;++++++++++
 1 file changed, 82 insertions(+)

diff --git a/meta/classes/base.bbclass b/meta/classes/base.bbclass
index e29821f..f2b2d97 100644
--- a/meta/classes/base.bbclass
+++ b/meta/classes/base.bbclass
@@ -10,6 +10,52 @@ inherit utility-tasks
 inherit metadata_scm
 inherit logging

+def get_git_src_date_epoch(d, path):
+    import subprocess
+    saved_cwd =3D os.getcwd()
+    os.chdir(path)
+    src_date_epoch =3D int(subprocess.check_output(['gi= t','log','-1','--pretty=3D%ct']))
+    os.chdir(saved_cwd)
+    return src_date_epoch
+
+def create_src_date_epoch_stamp(d):
+    if d.getVar('BUILD_REPRODUCIBLE_BINARIES') =3D=3D '= 1':
+        path =3D d.getVar('S')
+        src_date_epoch =3D 0
+        filename_dbg =3D None
+
+        if path.endswith('/git'):
+            src_date_epoch =3D get_git_s= rc_date_epoch(d, path)
+        else:
+            exclude =3D set(["temp&= quot;, "licenses", "patches", "recipe-sysroot-nati= ve", "recipe-sysroot" ])
+            for root, dirs, files in os.= walk(path, topdown=3DTrue):
+                dirs[:] =3D [d= for d in dirs if d not in exclude]
+                if root.endswi= th('/git'):
+                    = src_date_epoch =3D get_git_src_date_epoch(d, root)
+                    = break
+
+                for fname in f= iles:
+                    = filename =3D os.path.join(root, fname)
+                    = try:
+                    =     mtime =3D int(os.path.getmtime(filename))
+                    = except:
+                    =     mtime =3D 0
+                    = if mtime > src_date_epoch:
+                    =     src_date_epoch =3D mtime
+                    =     filename_dbg =3D filename
+
+        # Most likely an empty folder
+        if src_date_epoch =3D=3D 0:
+            bb.warn("Unable to dete= rmine src_date_epoch! path:%s" % path)
+
+        f =3D open(os.path.join(path,'src_dat= e_epoch.txt'), 'w')
+        f.write(str(src_date_epoch))
+        f.close()
+
+        if filename_dbg !=3D None:
+            bb.debug(1," src_date_e= poch %d derived from: %s" % (src_date_epoch, filename_dbg))
+
+
 OE_IMPORTS +=3D "os sys time oe.path oe.utils oe.types oe.pa= ckage oe.packagegroup oe.sstatesig oe.lsb oe.cachedpath oe.license"  OE_IMPORTS[type] =3D "list"

@@ -173,6 +219,7 @@ python base_do_unpack() {
     try:
         fetcher =3D bb.fetch2.Fetch(src_uri, d)          fetcher.unpack(d.getVar('WORKDIR'))<= br> +        create_src_date_epoch_stamp(d)
     except bb.fetch2.BBFetchException as e:
         bb.fatal(str(e))
 }
@@ -383,9 +430,43 @@ def set_packagetriplet(d):

     settriplet(d, "PKGMLTRIPLETS", archs, tos, tv= s)

+
+export PYTHONHASHSEED
+export PERL_HASH_SEED
+export SOURCE_DATE_EPOCH
+
+BB_HASHBASE_WHITELIST +=3D "SOURCE_DATE_EPOCH PYTHONHASHSEED = PERL_HASH_SEED "
+
 python () {
     import string, re

+    # Create reproducible_environment
+
+    if d.getVar('BUILD_REPRODUCIBLE_BINARIES') =3D=3D '= 1':
+        import subprocess
+        d.setVar('PYTHONHASHSEED', '0')
+        d.setVar('PERL_HASH_SEED', '0')
+        d.setVar('TZ', 'UTC')
+
+        path =3D d.getVar('S')
+        epochfile =3D os.path.join(path,'src_date_= epoch.txt')
+        if os.path.isfile(epochfile):
+            f =3D open(epochfile, 'r') +            src_date_epoch =3D f.read()<= br> +            f.close()
+            bb.debug(1, "src_date_e= poch stamp found ---> stamp %s" % src_date_epoch)
+            d.setVar('SOURCE_DATE_EPOCH'= , src_date_epoch)
+        else:
+            bb.debug(1, "src_date_e= poch stamp not found.")
+            d.setVar('SOURCE_DATE_EPOCH'= , '0')
+    else:
+        if 'PYTHONHASHSEED' in os.environ:
+            del os.environ['PYTHONHASHSE= ED']
+        if 'PERL_HASH_SEED' in os.environ:
+            del os.environ['PERL_HASH_SE= ED']
+        if 'SOURCE_DATE_EPOCH' in os.environ:
+            del os.environ['SOURCE_DATE_= EPOCH']
+
     # Handle PACKAGECONFIG
     #
     # These take the form:
@@ -678,6 +759,7 @@ python () {
             bb.warn("Recipe %s is = marked as only being architecture specific but seems to have machine specif= ic packages?! The recipe may as well mark itself as machine specific direct= ly." % d.getVar("PN"))
 }

+
 addtask cleansstate after do_clean
 python do_cleansstate() {
         sstate_clean_cachefiles(d)
--
2.7.4


--_000_6E51916E4A1F32428260031F4C7CD2B61198C2F5ORSMSX112amrcor_--