summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Purdie <richard.purdie@linuxfoundation.org>2012-08-25 15:48:14 +0000
committerRichard Purdie <richard.purdie@linuxfoundation.org>2012-08-30 17:44:06 -0700
commit59260f952f8687ac67a17035307c6c0792728f1b (patch)
tree75a6f3150da489c715cf77a92e60e82e45d3b0ad
parentcfb502cc2b2ba39b1b6f970b2410190cca2ba0fc (diff)
downloadpoky-59260f952f8687ac67a17035307c6c0792728f1b.tar.gz
sstate.bbclass: Detect overwriting files in sstate controlled directories
We have a potential problem where two sstate packages try and touch the same file. This adds code which will print a warning whenever this happens. The implementation does but by maintaining a master file list and comparing file accesses against this. There are a number of places we have duplicate accesses which are harmless, mostly in the deploy directory so these are whitelisted. For now the code prints warnings, this could be strengthened in future to become error messages. Whilst working on this code on and off over the past few months various issues were uncovered, some serious. [YOCTO #238] (From OE-Core rev: 1f1b6f93d6b7aa8c9bd9bb5b1826997812e36932) Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--meta/classes/sstate.bbclass45
1 files changed, 44 insertions, 1 deletions
diff --git a/meta/classes/sstate.bbclass b/meta/classes/sstate.bbclass
index 6762e32cfb..02594a7d33 100644
--- a/meta/classes/sstate.bbclass
+++ b/meta/classes/sstate.bbclass
@@ -3,6 +3,7 @@ SSTATE_VERSION = "2"
3SSTATE_MANIFESTS ?= "${TMPDIR}/sstate-control" 3SSTATE_MANIFESTS ?= "${TMPDIR}/sstate-control"
4SSTATE_MANFILEBASE = "${SSTATE_MANIFESTS}/manifest-${SSTATE_MANMACH}-" 4SSTATE_MANFILEBASE = "${SSTATE_MANIFESTS}/manifest-${SSTATE_MANMACH}-"
5SSTATE_MANFILEPREFIX = "${SSTATE_MANFILEBASE}${PN}" 5SSTATE_MANFILEPREFIX = "${SSTATE_MANFILEBASE}${PN}"
6SSTATE_MASTERMANIFEST = "${SSTATE_MANIFESTS}/master.list"
6 7
7def generate_sstatefn(spec, hash, d): 8def generate_sstatefn(spec, hash, d):
8 if not hash: 9 if not hash:
@@ -17,6 +18,7 @@ SSTATE_EXTRAPATH = ""
17SSTATE_EXTRAPATHWILDCARD = "" 18SSTATE_EXTRAPATHWILDCARD = ""
18SSTATE_PATHSPEC = "${SSTATE_DIR}/${SSTATE_EXTRAPATHWILDCARD}*/${SSTATE_PKGSPEC}" 19SSTATE_PATHSPEC = "${SSTATE_DIR}/${SSTATE_EXTRAPATHWILDCARD}*/${SSTATE_PKGSPEC}"
19 20
21SSTATE_DUPWHITELIST = "${DEPLOY_DIR_IMAGE}/ ${DEPLOY_DIR}/licenses/ ${DEPLOY_DIR_IPK}/all/ ${DEPLOY_DIR_RPM}/all ${DEPLOY_DIR_DEB}/all/"
20 22
21SSTATE_SCAN_FILES ?= "*.la *-config *_config" 23SSTATE_SCAN_FILES ?= "*.la *-config *_config"
22SSTATE_SCAN_CMD ?= 'find ${SSTATE_BUILDDIR} \( -name "${@"\" -o -name \"".join(d.getVar("SSTATE_SCAN_FILES", True).split())}" \) -type f' 24SSTATE_SCAN_CMD ?= 'find ${SSTATE_BUILDDIR} \( -name "${@"\" -o -name \"".join(d.getVar("SSTATE_SCAN_FILES", True).split())}" \) -type f'
@@ -125,7 +127,6 @@ def sstate_install(ss, d):
125 locks.append(bb.utils.lockfile(lock)) 127 locks.append(bb.utils.lockfile(lock))
126 128
127 for state in ss['dirs']: 129 for state in ss['dirs']:
128 oe.path.copytree(state[1], state[2])
129 for walkroot, dirs, files in os.walk(state[1]): 130 for walkroot, dirs, files in os.walk(state[1]):
130 bb.debug(2, "Staging files from %s to %s" % (state[1], state[2])) 131 bb.debug(2, "Staging files from %s to %s" % (state[1], state[2]))
131 for file in files: 132 for file in files:
@@ -140,9 +141,35 @@ def sstate_install(ss, d):
140 if not dstdir.endswith("/"): 141 if not dstdir.endswith("/"):
141 dstdir = dstdir + "/" 142 dstdir = dstdir + "/"
142 shareddirs.append(dstdir) 143 shareddirs.append(dstdir)
144
145 # Check the file list for conflicts against the master manifest
146 mastermanifest = d.getVar("SSTATE_MASTERMANIFEST", True)
147 whitelist = d.getVar("SSTATE_DUPWHITELIST", True)
148 lock = bb.utils.lockfile(mastermanifest + ".lock")
149 fileslist = [line.strip() for line in open(mastermanifest)]
150 bb.utils.unlockfile(lock)
151 match = []
152 for f in sharedfiles:
153 if f in fileslist:
154 realmatch = True
155 for w in whitelist:
156 if f.startswith(w):
157 realmatch = False
158 break
159 if realmatch:
160 match.append(f)
161 if match:
162 bb.warn("The recipe is trying to install files into a shared area when those files already exist. Those files are:\n %s" % "\n ".join(match))
163
164 # Write out the manifest and add to the task's manifest file
165 lock = bb.utils.lockfile(mastermanifest + ".lock")
166 mf = open(mastermanifest, "a")
143 f = open(manifest, "w") 167 f = open(manifest, "w")
144 for file in sharedfiles: 168 for file in sharedfiles:
169 mf.write(file + "\n")
145 f.write(file + "\n") 170 f.write(file + "\n")
171 bb.utils.unlockfile(lock)
172
146 # We want to ensure that directories appear at the end of the manifest 173 # We want to ensure that directories appear at the end of the manifest
147 # so that when we test to see if they should be deleted any contents 174 # so that when we test to see if they should be deleted any contents
148 # added by the task will have been removed first. 175 # added by the task will have been removed first.
@@ -152,6 +179,10 @@ def sstate_install(ss, d):
152 f.write(di + "\n") 179 f.write(di + "\n")
153 f.close() 180 f.close()
154 181
182 # Run the actual file install
183 for state in ss['dirs']:
184 oe.path.copytree(state[1], state[2])
185
155 for postinst in (d.getVar('SSTATEPOSTINSTFUNCS', True) or '').split(): 186 for postinst in (d.getVar('SSTATEPOSTINSTFUNCS', True) or '').split():
156 bb.build.exec_func(postinst, d) 187 bb.build.exec_func(postinst, d)
157 188
@@ -268,6 +299,18 @@ def sstate_clean_manifest(manifest, d):
268 except OSError: 299 except OSError:
269 pass 300 pass
270 301
302 # Remove the entries from the master manifest
303 mastermanifest = d.getVar("SSTATE_MASTERMANIFEST", True)
304 lock = bb.utils.lockfile(mastermanifest + ".lock")
305 mf = open(mastermanifest + ".new", "w")
306 for line in open(mastermanifest, "r"):
307 if not line or line in entries:
308 continue
309 mf.write(line)
310 mf.close()
311 os.rename(mastermanifest + ".new", mastermanifest)
312 bb.utils.unlockfile(lock)
313
271 oe.path.remove(manifest) 314 oe.path.remove(manifest)
272 315
273def sstate_clean(ss, d): 316def sstate_clean(ss, d):