| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 1 | # | 
 | 2 | # Sanity check the users setup for common misconfigurations | 
 | 3 | # | 
 | 4 |  | 
 | 5 | SANITY_REQUIRED_UTILITIES ?= "patch diffstat makeinfo git bzip2 tar \ | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 6 |     gzip gawk chrpath wget cpio perl file which" | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 7 |  | 
 | 8 | def bblayers_conf_file(d): | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 9 |     return os.path.join(d.getVar('TOPDIR'), 'conf/bblayers.conf') | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 10 |  | 
 | 11 | def sanity_conf_read(fn): | 
 | 12 |     with open(fn, 'r') as f: | 
 | 13 |         lines = f.readlines() | 
 | 14 |     return lines | 
 | 15 |  | 
 | 16 | def sanity_conf_find_line(pattern, lines): | 
 | 17 |     import re | 
 | 18 |     return next(((index, line) | 
 | 19 |         for index, line in enumerate(lines) | 
 | 20 |         if re.search(pattern, line)), (None, None)) | 
 | 21 |  | 
 | 22 | def sanity_conf_update(fn, lines, version_var_name, new_version): | 
| Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 23 |     index, line = sanity_conf_find_line(r"^%s" % version_var_name, lines) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 24 |     lines[index] = '%s = "%d"\n' % (version_var_name, new_version) | 
 | 25 |     with open(fn, "w") as f: | 
 | 26 |         f.write(''.join(lines)) | 
 | 27 |  | 
| Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 28 | # Functions added to this variable MUST throw a NotImplementedError exception unless  | 
 | 29 | # they successfully changed the config version in the config file. Exceptions | 
 | 30 | # are used since exec_func doesn't handle return values. | 
 | 31 | BBLAYERS_CONF_UPDATE_FUNCS += " \ | 
 | 32 |     conf/bblayers.conf:LCONF_VERSION:LAYER_CONF_VERSION:oecore_update_bblayers \ | 
 | 33 |     conf/local.conf:CONF_VERSION:LOCALCONF_VERSION:oecore_update_localconf \ | 
 | 34 |     conf/site.conf:SCONF_VERSION:SITE_CONF_VERSION:oecore_update_siteconf \ | 
 | 35 | " | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 36 |  | 
| Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 37 | SANITY_DIFF_TOOL ?= "meld" | 
 | 38 |  | 
 | 39 | SANITY_LOCALCONF_SAMPLE ?= "${COREBASE}/meta*/conf/local.conf.sample" | 
 | 40 | python oecore_update_localconf() { | 
 | 41 |     # Check we are using a valid local.conf | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 42 |     current_conf  = d.getVar('CONF_VERSION') | 
 | 43 |     conf_version =  d.getVar('LOCALCONF_VERSION') | 
| Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 44 |  | 
 | 45 |     failmsg = """Your version of local.conf was generated from an older/newer version of  | 
 | 46 | local.conf.sample and there have been updates made to this file. Please compare the two  | 
 | 47 | files and merge any changes before continuing. | 
 | 48 |  | 
 | 49 | Matching the version numbers will remove this message. | 
 | 50 |  | 
 | 51 | \"${SANITY_DIFF_TOOL} conf/local.conf ${SANITY_LOCALCONF_SAMPLE}\"  | 
 | 52 |  | 
 | 53 | is a good way to visualise the changes.""" | 
 | 54 |     failmsg = d.expand(failmsg) | 
 | 55 |  | 
 | 56 |     raise NotImplementedError(failmsg) | 
 | 57 | } | 
 | 58 |  | 
 | 59 | SANITY_SITECONF_SAMPLE ?= "${COREBASE}/meta*/conf/site.conf.sample" | 
 | 60 | python oecore_update_siteconf() { | 
 | 61 |     # If we have a site.conf, check it's valid | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 62 |     current_sconf = d.getVar('SCONF_VERSION') | 
 | 63 |     sconf_version = d.getVar('SITE_CONF_VERSION') | 
| Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 64 |  | 
 | 65 |     failmsg = """Your version of site.conf was generated from an older version of  | 
 | 66 | site.conf.sample and there have been updates made to this file. Please compare the two  | 
 | 67 | files and merge any changes before continuing. | 
 | 68 |  | 
 | 69 | Matching the version numbers will remove this message. | 
 | 70 |  | 
 | 71 | \"${SANITY_DIFF_TOOL} conf/site.conf ${SANITY_SITECONF_SAMPLE}\"  | 
 | 72 |  | 
 | 73 | is a good way to visualise the changes.""" | 
 | 74 |     failmsg = d.expand(failmsg) | 
 | 75 |  | 
 | 76 |     raise NotImplementedError(failmsg) | 
 | 77 | } | 
 | 78 |  | 
 | 79 | SANITY_BBLAYERCONF_SAMPLE ?= "${COREBASE}/meta*/conf/bblayers.conf.sample" | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 80 | python oecore_update_bblayers() { | 
 | 81 |     # bblayers.conf is out of date, so see if we can resolve that | 
 | 82 |  | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 83 |     current_lconf = int(d.getVar('LCONF_VERSION')) | 
 | 84 |     lconf_version = int(d.getVar('LAYER_CONF_VERSION')) | 
| Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 85 |  | 
 | 86 |     failmsg = """Your version of bblayers.conf has the wrong LCONF_VERSION (has ${LCONF_VERSION}, expecting ${LAYER_CONF_VERSION}). | 
 | 87 | Please compare your file against bblayers.conf.sample and merge any changes before continuing. | 
 | 88 | "${SANITY_DIFF_TOOL} conf/bblayers.conf ${SANITY_BBLAYERCONF_SAMPLE}"  | 
 | 89 |  | 
 | 90 | is a good way to visualise the changes.""" | 
 | 91 |     failmsg = d.expand(failmsg) | 
 | 92 |  | 
 | 93 |     if not current_lconf: | 
 | 94 |         raise NotImplementedError(failmsg) | 
 | 95 |  | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 96 |     lines = [] | 
 | 97 |  | 
 | 98 |     if current_lconf < 4: | 
| Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 99 |         raise NotImplementedError(failmsg) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 100 |  | 
 | 101 |     bblayers_fn = bblayers_conf_file(d) | 
 | 102 |     lines = sanity_conf_read(bblayers_fn) | 
 | 103 |  | 
 | 104 |     if current_lconf == 4 and lconf_version > 4: | 
 | 105 |         topdir_var = '$' + '{TOPDIR}' | 
 | 106 |         index, bbpath_line = sanity_conf_find_line('BBPATH', lines) | 
 | 107 |         if bbpath_line: | 
 | 108 |             start = bbpath_line.find('"') | 
 | 109 |             if start != -1 and (len(bbpath_line) != (start + 1)): | 
 | 110 |                 if bbpath_line[start + 1] == '"': | 
 | 111 |                     lines[index] = (bbpath_line[:start + 1] + | 
 | 112 |                                     topdir_var + bbpath_line[start + 1:]) | 
 | 113 |                 else: | 
 | 114 |                     if not topdir_var in bbpath_line: | 
 | 115 |                         lines[index] = (bbpath_line[:start + 1] + | 
 | 116 |                                     topdir_var + ':' + bbpath_line[start + 1:]) | 
 | 117 |             else: | 
| Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 118 |                 raise NotImplementedError(failmsg) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 119 |         else: | 
 | 120 |             index, bbfiles_line = sanity_conf_find_line('BBFILES', lines) | 
 | 121 |             if bbfiles_line: | 
 | 122 |                 lines.insert(index, 'BBPATH = "' + topdir_var + '"\n') | 
 | 123 |             else: | 
| Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 124 |                 raise NotImplementedError(failmsg) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 125 |  | 
 | 126 |         current_lconf += 1 | 
 | 127 |         sanity_conf_update(bblayers_fn, lines, 'LCONF_VERSION', current_lconf) | 
| Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 128 |         bb.note("Your conf/bblayers.conf has been automatically updated.") | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 129 |         return | 
 | 130 |  | 
 | 131 |     elif current_lconf == 5 and lconf_version > 5: | 
 | 132 |         # Null update, to avoid issues with people switching between poky and other distros | 
 | 133 |         current_lconf = 6 | 
 | 134 |         sanity_conf_update(bblayers_fn, lines, 'LCONF_VERSION', current_lconf) | 
| Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 135 |         bb.note("Your conf/bblayers.conf has been automatically updated.") | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 136 |         return | 
 | 137 |  | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 138 |         status.addresult() | 
| Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 139 |  | 
 | 140 |     elif current_lconf == 6 and lconf_version > 6: | 
 | 141 |         # Handle rename of meta-yocto -> meta-poky | 
 | 142 |         # This marks the start of separate version numbers but code is needed in OE-Core | 
 | 143 |         # for the migration, one last time. | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 144 |         layers = d.getVar('BBLAYERS').split() | 
| Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 145 |         layers = [ os.path.basename(path) for path in layers ] | 
 | 146 |         if 'meta-yocto' in layers: | 
 | 147 |             found = False | 
 | 148 |             while True: | 
 | 149 |                 index, meta_yocto_line = sanity_conf_find_line(r'.*meta-yocto[\'"\s\n]', lines) | 
 | 150 |                 if meta_yocto_line: | 
 | 151 |                     lines[index] = meta_yocto_line.replace('meta-yocto', 'meta-poky') | 
 | 152 |                     found = True | 
 | 153 |                 else: | 
 | 154 |                     break | 
 | 155 |             if not found: | 
 | 156 |                 raise NotImplementedError(failmsg) | 
 | 157 |             index, meta_yocto_line = sanity_conf_find_line('LCONF_VERSION.*\n', lines) | 
 | 158 |             if meta_yocto_line: | 
 | 159 |                 lines[index] = 'POKY_BBLAYERS_CONF_VERSION = "1"\n' | 
 | 160 |             else: | 
 | 161 |                 raise NotImplementedError(failmsg) | 
 | 162 |             with open(bblayers_fn, "w") as f: | 
 | 163 |                 f.write(''.join(lines)) | 
 | 164 |             bb.note("Your conf/bblayers.conf has been automatically updated.") | 
 | 165 |             return | 
 | 166 |         current_lconf += 1 | 
 | 167 |         sanity_conf_update(bblayers_fn, lines, 'LCONF_VERSION', current_lconf) | 
 | 168 |         bb.note("Your conf/bblayers.conf has been automatically updated.") | 
 | 169 |         return | 
 | 170 |  | 
 | 171 |     raise NotImplementedError(failmsg) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 172 | } | 
 | 173 |  | 
 | 174 | def raise_sanity_error(msg, d, network_error=False): | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 175 |     if d.getVar("SANITY_USE_EVENTS") == "1": | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 176 |         try: | 
 | 177 |             bb.event.fire(bb.event.SanityCheckFailed(msg, network_error), d) | 
 | 178 |         except TypeError: | 
 | 179 |             bb.event.fire(bb.event.SanityCheckFailed(msg), d) | 
 | 180 |         return | 
 | 181 |  | 
 | 182 |     bb.fatal(""" OE-core's config sanity checker detected a potential misconfiguration. | 
 | 183 |     Either fix the cause of this error or at your own risk disable the checker (see sanity.conf). | 
 | 184 |     Following is the list of potential problems / advisories: | 
 | 185 |      | 
 | 186 |     %s""" % msg) | 
 | 187 |  | 
 | 188 | # Check flags associated with a tuning. | 
 | 189 | def check_toolchain_tune_args(data, tune, multilib, errs): | 
 | 190 |     found_errors = False | 
 | 191 |     if check_toolchain_args_present(data, tune, multilib, errs, 'CCARGS'): | 
 | 192 |         found_errors = True | 
 | 193 |     if check_toolchain_args_present(data, tune, multilib, errs, 'ASARGS'): | 
 | 194 |         found_errors = True | 
 | 195 |     if check_toolchain_args_present(data, tune, multilib, errs, 'LDARGS'): | 
 | 196 |         found_errors = True | 
 | 197 |  | 
 | 198 |     return found_errors | 
 | 199 |  | 
 | 200 | def check_toolchain_args_present(data, tune, multilib, tune_errors, which): | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 201 |     args_set = (data.getVar("TUNE_%s" % which) or "").split() | 
 | 202 |     args_wanted = (data.getVar("TUNEABI_REQUIRED_%s_tune-%s" % (which, tune)) or "").split() | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 203 |     args_missing = [] | 
 | 204 |  | 
 | 205 |     # If no args are listed/required, we are done. | 
 | 206 |     if not args_wanted: | 
 | 207 |         return | 
 | 208 |     for arg in args_wanted: | 
 | 209 |         if arg not in args_set: | 
 | 210 |             args_missing.append(arg) | 
 | 211 |  | 
 | 212 |     found_errors = False | 
 | 213 |     if args_missing: | 
 | 214 |         found_errors = True | 
 | 215 |         tune_errors.append("TUNEABI for %s requires '%s' in TUNE_%s (%s)." % | 
 | 216 |                        (tune, ' '.join(args_missing), which, ' '.join(args_set))) | 
 | 217 |     return found_errors | 
 | 218 |  | 
 | 219 | # Check a single tune for validity. | 
 | 220 | def check_toolchain_tune(data, tune, multilib): | 
 | 221 |     tune_errors = [] | 
 | 222 |     if not tune: | 
 | 223 |         return "No tuning found for %s multilib." % multilib | 
 | 224 |     localdata = bb.data.createCopy(data) | 
 | 225 |     if multilib != "default": | 
 | 226 |         # Apply the overrides so we can look at the details. | 
 | 227 |         overrides = localdata.getVar("OVERRIDES", False) + ":virtclass-multilib-" + multilib | 
 | 228 |         localdata.setVar("OVERRIDES", overrides) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 229 |     bb.debug(2, "Sanity-checking tuning '%s' (%s) features:" % (tune, multilib)) | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 230 |     features = (localdata.getVar("TUNE_FEATURES_tune-%s" % tune) or "").split() | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 231 |     if not features: | 
 | 232 |         return "Tuning '%s' has no defined features, and cannot be used." % tune | 
 | 233 |     valid_tunes = localdata.getVarFlags('TUNEVALID') or {} | 
 | 234 |     conflicts = localdata.getVarFlags('TUNECONFLICTS') or {} | 
 | 235 |     # [doc] is the documentation for the variable, not a real feature | 
 | 236 |     if 'doc' in valid_tunes: | 
 | 237 |         del valid_tunes['doc'] | 
 | 238 |     if 'doc' in conflicts: | 
 | 239 |         del conflicts['doc'] | 
 | 240 |     for feature in features: | 
 | 241 |         if feature in conflicts: | 
 | 242 |             for conflict in conflicts[feature].split(): | 
 | 243 |                 if conflict in features: | 
 | 244 |                     tune_errors.append("Feature '%s' conflicts with '%s'." % | 
 | 245 |                         (feature, conflict)) | 
 | 246 |         if feature in valid_tunes: | 
 | 247 |             bb.debug(2, "  %s: %s" % (feature, valid_tunes[feature])) | 
 | 248 |         else: | 
 | 249 |             tune_errors.append("Feature '%s' is not defined." % feature) | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 250 |     whitelist = localdata.getVar("TUNEABI_WHITELIST") | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 251 |     if whitelist: | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 252 |         tuneabi = localdata.getVar("TUNEABI_tune-%s" % tune) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 253 |         if not tuneabi: | 
 | 254 |             tuneabi = tune | 
 | 255 |         if True not in [x in whitelist.split() for x in tuneabi.split()]: | 
 | 256 |             tune_errors.append("Tuning '%s' (%s) cannot be used with any supported tuning/ABI." % | 
 | 257 |                 (tune, tuneabi)) | 
 | 258 |         else: | 
 | 259 |             if not check_toolchain_tune_args(localdata, tuneabi, multilib, tune_errors): | 
 | 260 |                 bb.debug(2, "Sanity check: Compiler args OK for %s." % tune) | 
 | 261 |     if tune_errors: | 
 | 262 |         return "Tuning '%s' has the following errors:\n" % tune + '\n'.join(tune_errors) | 
 | 263 |  | 
 | 264 | def check_toolchain(data): | 
 | 265 |     tune_error_set = [] | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 266 |     deftune = data.getVar("DEFAULTTUNE") | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 267 |     tune_errors = check_toolchain_tune(data, deftune, 'default') | 
 | 268 |     if tune_errors: | 
 | 269 |         tune_error_set.append(tune_errors) | 
 | 270 |  | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 271 |     multilibs = (data.getVar("MULTILIB_VARIANTS") or "").split() | 
 | 272 |     global_multilibs = (data.getVar("MULTILIB_GLOBAL_VARIANTS") or "").split() | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 273 |  | 
 | 274 |     if multilibs: | 
 | 275 |         seen_libs = [] | 
 | 276 |         seen_tunes = [] | 
 | 277 |         for lib in multilibs: | 
 | 278 |             if lib in seen_libs: | 
 | 279 |                 tune_error_set.append("The multilib '%s' appears more than once." % lib) | 
 | 280 |             else: | 
 | 281 |                 seen_libs.append(lib) | 
 | 282 |             if not lib in global_multilibs: | 
 | 283 |                 tune_error_set.append("Multilib %s is not present in MULTILIB_GLOBAL_VARIANTS" % lib) | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 284 |             tune = data.getVar("DEFAULTTUNE_virtclass-multilib-%s" % lib) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 285 |             if tune in seen_tunes: | 
 | 286 |                 tune_error_set.append("The tuning '%s' appears in more than one multilib." % tune) | 
 | 287 |             else: | 
 | 288 |                 seen_libs.append(tune) | 
 | 289 |             if tune == deftune: | 
 | 290 |                 tune_error_set.append("Multilib '%s' (%s) is also the default tuning." % (lib, deftune)) | 
 | 291 |             else: | 
 | 292 |                 tune_errors = check_toolchain_tune(data, tune, lib) | 
 | 293 |             if tune_errors: | 
 | 294 |                 tune_error_set.append(tune_errors) | 
 | 295 |     if tune_error_set: | 
 | 296 |         return "Toolchain tunings invalid:\n" + '\n'.join(tune_error_set) + "\n" | 
 | 297 |  | 
 | 298 |     return "" | 
 | 299 |  | 
 | 300 | def check_conf_exists(fn, data): | 
 | 301 |     bbpath = [] | 
 | 302 |     fn = data.expand(fn) | 
 | 303 |     vbbpath = data.getVar("BBPATH", False) | 
 | 304 |     if vbbpath: | 
 | 305 |         bbpath += vbbpath.split(":") | 
 | 306 |     for p in bbpath: | 
 | 307 |         currname = os.path.join(data.expand(p), fn) | 
 | 308 |         if os.access(currname, os.R_OK): | 
 | 309 |             return True | 
 | 310 |     return False | 
 | 311 |  | 
 | 312 | def check_create_long_filename(filepath, pathname): | 
 | 313 |     import string, random | 
 | 314 |     testfile = os.path.join(filepath, ''.join(random.choice(string.ascii_letters) for x in range(200))) | 
 | 315 |     try: | 
 | 316 |         if not os.path.exists(filepath): | 
 | 317 |             bb.utils.mkdirhier(filepath) | 
 | 318 |         f = open(testfile, "w") | 
 | 319 |         f.close() | 
 | 320 |         os.remove(testfile) | 
 | 321 |     except IOError as e: | 
 | 322 |         import errno | 
 | 323 |         err, strerror = e.args | 
 | 324 |         if err == errno.ENAMETOOLONG: | 
 | 325 |             return "Failed to create a file with a long name in %s. Please use a filesystem that does not unreasonably limit filename length.\n" % pathname | 
 | 326 |         else: | 
 | 327 |             return "Failed to create a file in %s: %s.\n" % (pathname, strerror) | 
 | 328 |     except OSError as e: | 
 | 329 |         errno, strerror = e.args | 
 | 330 |         return "Failed to create %s directory in which to run long name sanity check: %s.\n" % (pathname, strerror) | 
 | 331 |     return "" | 
 | 332 |  | 
 | 333 | def check_path_length(filepath, pathname, limit): | 
 | 334 |     if len(filepath) > limit: | 
| Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 335 |         return "The length of %s is longer than %s, this would cause unexpected errors, please use a shorter path.\n" % (pathname, limit) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 336 |     return "" | 
 | 337 |  | 
 | 338 | def get_filesystem_id(path): | 
| Brad Bishop | d5ae7d9 | 2018-06-14 09:52:03 -0700 | [diff] [blame] | 339 |     import subprocess | 
 | 340 |     try: | 
 | 341 |         return subprocess.check_output(["stat", "-f", "-c", "%t", path]).decode('utf-8') | 
 | 342 |     except subprocess.CalledProcessError: | 
 | 343 |         bb.warn("Can't get filesystem id of: %s" % path) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 344 |         return None | 
 | 345 |  | 
 | 346 | # Check that the path isn't located on nfs. | 
 | 347 | def check_not_nfs(path, name): | 
 | 348 |     # The nfs' filesystem id is 6969 | 
 | 349 |     if get_filesystem_id(path) == "6969": | 
 | 350 |         return "The %s: %s can't be located on nfs.\n" % (name, path) | 
 | 351 |     return "" | 
 | 352 |  | 
| Brad Bishop | d7bf8c1 | 2018-02-25 22:55:05 -0500 | [diff] [blame] | 353 | # Check that the path is on a case-sensitive file system | 
 | 354 | def check_case_sensitive(path, name): | 
 | 355 |     import tempfile | 
 | 356 |     with tempfile.NamedTemporaryFile(prefix='TmP', dir=path) as tmp_file: | 
 | 357 |         if os.path.exists(tmp_file.name.lower()): | 
 | 358 |             return "The %s (%s) can't be on a case-insensitive file system.\n" % (name, path) | 
 | 359 |         return "" | 
 | 360 |  | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 361 | # Check that path isn't a broken symlink | 
 | 362 | def check_symlink(lnk, data): | 
 | 363 |     if os.path.islink(lnk) and not os.path.exists(lnk): | 
 | 364 |         raise_sanity_error("%s is a broken symlink." % lnk, data) | 
 | 365 |  | 
 | 366 | def check_connectivity(d): | 
 | 367 |     # URI's to check can be set in the CONNECTIVITY_CHECK_URIS variable | 
 | 368 |     # using the same syntax as for SRC_URI. If the variable is not set | 
 | 369 |     # the check is skipped | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 370 |     test_uris = (d.getVar('CONNECTIVITY_CHECK_URIS') or "").split() | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 371 |     retval = "" | 
 | 372 |  | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 373 |     bbn = d.getVar('BB_NO_NETWORK') | 
 | 374 |     if bbn not in (None, '0', '1'): | 
 | 375 |         return 'BB_NO_NETWORK should be "0" or "1", but it is "%s"' % bbn | 
 | 376 |  | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 377 |     # Only check connectivity if network enabled and the | 
 | 378 |     # CONNECTIVITY_CHECK_URIS are set | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 379 |     network_enabled = not (bbn == '1') | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 380 |     check_enabled = len(test_uris) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 381 |     if check_enabled and network_enabled: | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 382 |         # Take a copy of the data store and unset MIRRORS and PREMIRRORS | 
 | 383 |         data = bb.data.createCopy(d) | 
 | 384 |         data.delVar('PREMIRRORS') | 
 | 385 |         data.delVar('MIRRORS') | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 386 |         try: | 
 | 387 |             fetcher = bb.fetch2.Fetch(test_uris, data) | 
 | 388 |             fetcher.checkstatus() | 
 | 389 |         except Exception as err: | 
 | 390 |             # Allow the message to be configured so that users can be | 
 | 391 |             # pointed to a support mechanism. | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 392 |             msg = data.getVar('CONNECTIVITY_CHECK_MSG') or "" | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 393 |             if len(msg) == 0: | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 394 |                 msg = "%s.\n" % err | 
 | 395 |                 msg += "    Please ensure your host's network is configured correctly,\n" | 
 | 396 |                 msg += "    or set BB_NO_NETWORK = \"1\" to disable network access if\n" | 
 | 397 |                 msg += "    all required sources are on local disk.\n" | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 398 |             retval = msg | 
 | 399 |  | 
 | 400 |     return retval | 
 | 401 |  | 
 | 402 | def check_supported_distro(sanity_data): | 
 | 403 |     from fnmatch import fnmatch | 
 | 404 |  | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 405 |     tested_distros = sanity_data.getVar('SANITY_TESTED_DISTROS') | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 406 |     if not tested_distros: | 
 | 407 |         return | 
 | 408 |  | 
 | 409 |     try: | 
 | 410 |         distro = oe.lsb.distro_identifier() | 
 | 411 |     except Exception: | 
 | 412 |         distro = None | 
 | 413 |  | 
 | 414 |     if not distro: | 
 | 415 |         bb.warn('Host distribution could not be determined; you may possibly experience unexpected failures. It is recommended that you use a tested distribution.') | 
 | 416 |  | 
 | 417 |     for supported in [x.strip() for x in tested_distros.split('\\n')]: | 
 | 418 |         if fnmatch(distro, supported): | 
 | 419 |             return | 
 | 420 |  | 
 | 421 |     bb.warn('Host distribution "%s" has not been validated with this version of the build system; you may possibly experience unexpected failures. It is recommended that you use a tested distribution.' % distro) | 
 | 422 |  | 
 | 423 | # Checks we should only make if MACHINE is set correctly | 
 | 424 | def check_sanity_validmachine(sanity_data): | 
 | 425 |     messages = "" | 
 | 426 |  | 
 | 427 |     # Check TUNE_ARCH is set | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 428 |     if sanity_data.getVar('TUNE_ARCH') == 'INVALID': | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 429 |         messages = messages + 'TUNE_ARCH is unset. Please ensure your MACHINE configuration includes a valid tune configuration file which will set this correctly.\n' | 
 | 430 |  | 
 | 431 |     # Check TARGET_OS is set | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 432 |     if sanity_data.getVar('TARGET_OS') == 'INVALID': | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 433 |         messages = messages + 'Please set TARGET_OS directly, or choose a MACHINE or DISTRO that does so.\n' | 
 | 434 |  | 
 | 435 |     # Check that we don't have duplicate entries in PACKAGE_ARCHS & that TUNE_PKGARCH is in PACKAGE_ARCHS | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 436 |     pkgarchs = sanity_data.getVar('PACKAGE_ARCHS') | 
 | 437 |     tunepkg = sanity_data.getVar('TUNE_PKGARCH') | 
 | 438 |     defaulttune = sanity_data.getVar('DEFAULTTUNE') | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 439 |     tunefound = False | 
 | 440 |     seen = {} | 
 | 441 |     dups = [] | 
 | 442 |  | 
 | 443 |     for pa in pkgarchs.split(): | 
 | 444 |         if seen.get(pa, 0) == 1: | 
 | 445 |             dups.append(pa) | 
 | 446 |         else: | 
 | 447 |             seen[pa] = 1 | 
 | 448 |         if pa == tunepkg: | 
 | 449 |             tunefound = True | 
 | 450 |  | 
 | 451 |     if len(dups): | 
 | 452 |         messages = messages + "Error, the PACKAGE_ARCHS variable contains duplicates. The following archs are listed more than once: %s" % " ".join(dups) | 
 | 453 |  | 
 | 454 |     if tunefound == False: | 
| Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 455 |         messages = messages + "Error, the PACKAGE_ARCHS variable (%s) for DEFAULTTUNE (%s) does not contain TUNE_PKGARCH (%s)." % (pkgarchs, defaulttune, tunepkg) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 456 |  | 
 | 457 |     return messages | 
 | 458 |  | 
| Brad Bishop | 316dfdd | 2018-06-25 12:45:53 -0400 | [diff] [blame] | 459 | # Patch before 2.7 can't handle all the features in git-style diffs.  Some | 
 | 460 | # patches may incorrectly apply, and others won't apply at all. | 
 | 461 | def check_patch_version(sanity_data): | 
 | 462 |     from distutils.version import LooseVersion | 
 | 463 |     import re, subprocess | 
 | 464 |  | 
 | 465 |     try: | 
| Brad Bishop | d5ae7d9 | 2018-06-14 09:52:03 -0700 | [diff] [blame] | 466 |         result = subprocess.check_output(["patch", "--version"], stderr=subprocess.STDOUT).decode('utf-8') | 
| Brad Bishop | 316dfdd | 2018-06-25 12:45:53 -0400 | [diff] [blame] | 467 |         version = re.search(r"[0-9.]+", result.splitlines()[0]).group() | 
 | 468 |         if LooseVersion(version) < LooseVersion("2.7"): | 
 | 469 |             return "Your version of patch is older than 2.7 and has bugs which will break builds. Please install a newer version of patch.\n" | 
 | 470 |         else: | 
 | 471 |             return None | 
 | 472 |     except subprocess.CalledProcessError as e: | 
 | 473 |         return "Unable to execute patch --version, exit code %d:\n%s\n" % (e.returncode, e.output) | 
 | 474 |  | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 475 | # Unpatched versions of make 3.82 are known to be broken.  See GNU Savannah Bug 30612. | 
 | 476 | # Use a modified reproducer from http://savannah.gnu.org/bugs/?30612 to validate. | 
 | 477 | def check_make_version(sanity_data): | 
 | 478 |     from distutils.version import LooseVersion | 
| Brad Bishop | d5ae7d9 | 2018-06-14 09:52:03 -0700 | [diff] [blame] | 479 |     import subprocess | 
 | 480 |  | 
 | 481 |     try: | 
 | 482 |         result = subprocess.check_output(['make', '--version'], stderr=subprocess.STDOUT).decode('utf-8') | 
 | 483 |     except subprocess.CalledProcessError as e: | 
 | 484 |         return "Unable to execute make --version, exit code %d\n%s\n" % (e.returncode, e.output) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 485 |     version = result.split()[2] | 
 | 486 |     if LooseVersion(version) == LooseVersion("3.82"): | 
 | 487 |         # Construct a test file | 
 | 488 |         f = open("makefile_test", "w") | 
 | 489 |         f.write("makefile_test.a: makefile_test_a.c makefile_test_b.c makefile_test.a( makefile_test_a.c makefile_test_b.c)\n") | 
 | 490 |         f.write("\n") | 
 | 491 |         f.write("makefile_test_a.c:\n") | 
 | 492 |         f.write("	touch $@\n") | 
 | 493 |         f.write("\n") | 
 | 494 |         f.write("makefile_test_b.c:\n") | 
 | 495 |         f.write("	touch $@\n") | 
 | 496 |         f.close() | 
 | 497 |  | 
 | 498 |         # Check if make 3.82 has been patched | 
| Brad Bishop | d5ae7d9 | 2018-06-14 09:52:03 -0700 | [diff] [blame] | 499 |         try: | 
 | 500 |             subprocess.check_call(['make', '-f', 'makefile_test']) | 
 | 501 |         except subprocess.CalledProcessError as e: | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 502 |             return "Your version of make 3.82 is broken. Please revert to 3.81 or install a patched version.\n" | 
| Brad Bishop | d5ae7d9 | 2018-06-14 09:52:03 -0700 | [diff] [blame] | 503 |         finally: | 
 | 504 |             os.remove("makefile_test") | 
 | 505 |             if os.path.exists("makefile_test_a.c"): | 
 | 506 |                 os.remove("makefile_test_a.c") | 
 | 507 |             if os.path.exists("makefile_test_b.c"): | 
 | 508 |                 os.remove("makefile_test_b.c") | 
 | 509 |             if os.path.exists("makefile_test.a"): | 
 | 510 |                 os.remove("makefile_test.a") | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 511 |     return None | 
 | 512 |  | 
 | 513 |  | 
 | 514 | # Tar version 1.24 and onwards handle overwriting symlinks correctly | 
 | 515 | # but earlier versions do not; this needs to work properly for sstate | 
 | 516 | def check_tar_version(sanity_data): | 
 | 517 |     from distutils.version import LooseVersion | 
| Brad Bishop | d5ae7d9 | 2018-06-14 09:52:03 -0700 | [diff] [blame] | 518 |     import subprocess | 
 | 519 |     try: | 
 | 520 |         result = subprocess.check_output(["tar", "--version"], stderr=subprocess.STDOUT).decode('utf-8') | 
 | 521 |     except subprocess.CalledProcessError as e: | 
 | 522 |         return "Unable to execute tar --version, exit code %d\n%s\n" % (e.returncode, e.output) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 523 |     version = result.split()[3] | 
 | 524 |     if LooseVersion(version) < LooseVersion("1.24"): | 
 | 525 |         return "Your version of tar is older than 1.24 and has bugs which will break builds. Please install a newer version of tar.\n" | 
 | 526 |     return None | 
 | 527 |  | 
 | 528 | # We use git parameters and functionality only found in 1.7.8 or later | 
| Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 529 | # The kernel tools assume git >= 1.8.3.1 (verified needed > 1.7.9.5) see #6162  | 
 | 530 | # The git fetcher also had workarounds for git < 1.7.9.2 which we've dropped | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 531 | def check_git_version(sanity_data): | 
 | 532 |     from distutils.version import LooseVersion | 
| Brad Bishop | d5ae7d9 | 2018-06-14 09:52:03 -0700 | [diff] [blame] | 533 |     import subprocess | 
 | 534 |     try: | 
 | 535 |         result = subprocess.check_output(["git", "--version"], stderr=subprocess.DEVNULL).decode('utf-8') | 
 | 536 |     except subprocess.CalledProcessError as e: | 
 | 537 |         return "Unable to execute git --version, exit code %d\n%s\n" % (e.returncode, e.output) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 538 |     version = result.split()[2] | 
| Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 539 |     if LooseVersion(version) < LooseVersion("1.8.3.1"): | 
 | 540 |         return "Your version of git is older than 1.8.3.1 and has bugs which will break builds. Please install a newer version of git.\n" | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 541 |     return None | 
 | 542 |  | 
 | 543 | # Check the required perl modules which may not be installed by default | 
 | 544 | def check_perl_modules(sanity_data): | 
| Brad Bishop | d5ae7d9 | 2018-06-14 09:52:03 -0700 | [diff] [blame] | 545 |     import subprocess | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 546 |     ret = "" | 
 | 547 |     modules = ( "Text::ParseWords", "Thread::Queue", "Data::Dumper" ) | 
| Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 548 |     errresult = '' | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 549 |     for m in modules: | 
| Brad Bishop | d5ae7d9 | 2018-06-14 09:52:03 -0700 | [diff] [blame] | 550 |         try: | 
 | 551 |             subprocess.check_output(["perl", "-e", "use %s" % m]) | 
 | 552 |         except subprocess.CalledProcessError as e: | 
 | 553 |             errresult += e.output | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 554 |             ret += "%s " % m | 
 | 555 |     if ret: | 
| Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 556 |         return "Required perl module(s) not found: %s\n\n%s\n" % (ret, errresult) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 557 |     return None | 
 | 558 |  | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 559 | def sanity_check_conffiles(d): | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 560 |     funcs = d.getVar('BBLAYERS_CONF_UPDATE_FUNCS').split() | 
| Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 561 |     for func in funcs: | 
 | 562 |         conffile, current_version, required_version, func = func.split(":") | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 563 |         if check_conf_exists(conffile, d) and d.getVar(current_version) is not None and \ | 
 | 564 |                 d.getVar(current_version) != d.getVar(required_version): | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 565 |             try: | 
| Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 566 |                 bb.build.exec_func(func, d, pythonexception=True) | 
 | 567 |             except NotImplementedError as e: | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 568 |                 bb.fatal(str(e)) | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 569 |             d.setVar("BB_INVALIDCONF", True) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 570 |  | 
 | 571 | def sanity_handle_abichanges(status, d): | 
 | 572 |     # | 
 | 573 |     # Check the 'ABI' of TMPDIR | 
 | 574 |     # | 
 | 575 |     import subprocess | 
 | 576 |  | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 577 |     current_abi = d.getVar('OELAYOUT_ABI') | 
 | 578 |     abifile = d.getVar('SANITY_ABIFILE') | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 579 |     if os.path.exists(abifile): | 
 | 580 |         with open(abifile, "r") as f: | 
 | 581 |             abi = f.read().strip() | 
 | 582 |         if not abi.isdigit(): | 
 | 583 |             with open(abifile, "w") as f: | 
 | 584 |                 f.write(current_abi) | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 585 |         elif int(abi) <= 11 and current_abi == "12": | 
 | 586 |             status.addresult("The layout of TMPDIR changed for Recipe Specific Sysroots.\nConversion doesn't make sense and this change will rebuild everything so please delete TMPDIR (%s).\n" % d.getVar("TMPDIR")) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 587 |         elif (abi != current_abi): | 
 | 588 |             # Code to convert from one ABI to another could go here if possible. | 
 | 589 |             status.addresult("Error, TMPDIR has changed its layout version number (%s to %s) and you need to either rebuild, revert or adjust it at your own risk.\n" % (abi, current_abi)) | 
 | 590 |     else: | 
 | 591 |         with open(abifile, "w") as f: | 
 | 592 |             f.write(current_abi) | 
 | 593 |  | 
 | 594 | def check_sanity_sstate_dir_change(sstate_dir, data): | 
 | 595 |     # Sanity checks to be done when the value of SSTATE_DIR changes | 
 | 596 |  | 
 | 597 |     # Check that SSTATE_DIR isn't on a filesystem with limited filename length (eg. eCryptFS) | 
 | 598 |     testmsg = "" | 
 | 599 |     if sstate_dir != "": | 
 | 600 |         testmsg = check_create_long_filename(sstate_dir, "SSTATE_DIR") | 
 | 601 |         # If we don't have permissions to SSTATE_DIR, suggest the user set it as an SSTATE_MIRRORS | 
 | 602 |         try: | 
 | 603 |             err = testmsg.split(': ')[1].strip() | 
 | 604 |             if err == "Permission denied.": | 
 | 605 |                 testmsg = testmsg + "You could try using %s in SSTATE_MIRRORS rather than as an SSTATE_CACHE.\n" % (sstate_dir) | 
 | 606 |         except IndexError: | 
 | 607 |             pass | 
 | 608 |     return testmsg | 
| Brad Bishop | d7bf8c1 | 2018-02-25 22:55:05 -0500 | [diff] [blame] | 609 |  | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 610 | def check_sanity_version_change(status, d): | 
| Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 611 |     # Sanity checks to be done when SANITY_VERSION or NATIVELSBSTRING changes | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 612 |     # In other words, these tests run once in a given build directory and then  | 
| Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 613 |     # never again until the sanity version or host distrubution id/version changes. | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 614 |  | 
 | 615 |     # Check the python install is complete. glib-2.0-natives requries | 
 | 616 |     # xml.parsers.expat | 
 | 617 |     try: | 
 | 618 |         import xml.parsers.expat | 
 | 619 |     except ImportError: | 
 | 620 |         status.addresult('Your python is not a full install. Please install the module xml.parsers.expat (python-xml on openSUSE and SUSE Linux).\n') | 
 | 621 |     import stat | 
 | 622 |  | 
 | 623 |     status.addresult(check_make_version(d)) | 
| Brad Bishop | 316dfdd | 2018-06-25 12:45:53 -0400 | [diff] [blame] | 624 |     status.addresult(check_patch_version(d)) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 625 |     status.addresult(check_tar_version(d)) | 
 | 626 |     status.addresult(check_git_version(d)) | 
 | 627 |     status.addresult(check_perl_modules(d)) | 
 | 628 |  | 
 | 629 |     missing = "" | 
 | 630 |  | 
 | 631 |     if not check_app_exists("${MAKE}", d): | 
 | 632 |         missing = missing + "GNU make," | 
 | 633 |  | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 634 |     if not check_app_exists('${BUILD_CC}', d): | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 635 |         missing = missing + "C Compiler (%s)," % d.getVar("BUILD_CC") | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 636 |  | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 637 |     if not check_app_exists('${BUILD_CXX}', d): | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 638 |         missing = missing + "C++ Compiler (%s)," % d.getVar("BUILD_CXX") | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 639 |  | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 640 |     required_utilities = d.getVar('SANITY_REQUIRED_UTILITIES') | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 641 |  | 
 | 642 |     for util in required_utilities.split(): | 
 | 643 |         if not check_app_exists(util, d): | 
 | 644 |             missing = missing + "%s," % util | 
 | 645 |  | 
 | 646 |     if missing: | 
 | 647 |         missing = missing.rstrip(',') | 
 | 648 |         status.addresult("Please install the following missing utilities: %s\n" % missing) | 
 | 649 |  | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 650 |     assume_provided = d.getVar('ASSUME_PROVIDED').split() | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 651 |     # Check user doesn't have ASSUME_PROVIDED = instead of += in local.conf | 
 | 652 |     if "diffstat-native" not in assume_provided: | 
 | 653 |         status.addresult('Please use ASSUME_PROVIDED +=, not ASSUME_PROVIDED = in your local.conf\n') | 
 | 654 |  | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 655 |     # Check that TMPDIR isn't on a filesystem with limited filename length (eg. eCryptFS) | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 656 |     tmpdir = d.getVar('TMPDIR') | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 657 |     status.addresult(check_create_long_filename(tmpdir, "TMPDIR")) | 
 | 658 |     tmpdirmode = os.stat(tmpdir).st_mode | 
 | 659 |     if (tmpdirmode & stat.S_ISGID): | 
 | 660 |         status.addresult("TMPDIR is setgid, please don't build in a setgid directory") | 
 | 661 |     if (tmpdirmode & stat.S_ISUID): | 
 | 662 |         status.addresult("TMPDIR is setuid, please don't build in a setuid directory") | 
 | 663 |  | 
 | 664 |     # Some third-party software apparently relies on chmod etc. being suid root (!!) | 
 | 665 |     import stat | 
 | 666 |     suid_check_bins = "chown chmod mknod".split() | 
 | 667 |     for bin_cmd in suid_check_bins: | 
 | 668 |         bin_path = bb.utils.which(os.environ["PATH"], bin_cmd) | 
 | 669 |         if bin_path: | 
 | 670 |             bin_stat = os.stat(bin_path) | 
 | 671 |             if bin_stat.st_uid == 0 and bin_stat.st_mode & stat.S_ISUID: | 
 | 672 |                 status.addresult('%s has the setuid bit set. This interferes with pseudo and may cause other issues that break the build process.\n' % bin_path) | 
 | 673 |  | 
 | 674 |     # Check that we can fetch from various network transports | 
 | 675 |     netcheck = check_connectivity(d) | 
 | 676 |     status.addresult(netcheck) | 
 | 677 |     if netcheck: | 
 | 678 |         status.network_error = True | 
 | 679 |  | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 680 |     nolibs = d.getVar('NO32LIBS') | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 681 |     if not nolibs: | 
 | 682 |         lib32path = '/lib' | 
 | 683 |         if os.path.exists('/lib64') and ( os.path.islink('/lib64') or os.path.islink('/lib') ): | 
 | 684 |            lib32path = '/lib32' | 
 | 685 |  | 
 | 686 |         if os.path.exists('%s/libc.so.6' % lib32path) and not os.path.exists('/usr/include/gnu/stubs-32.h'): | 
 | 687 |             status.addresult("You have a 32-bit libc, but no 32-bit headers.  You must install the 32-bit libc headers.\n") | 
 | 688 |  | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 689 |     bbpaths = d.getVar('BBPATH').split(":") | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 690 |     if ("." in bbpaths or "./" in bbpaths or "" in bbpaths): | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 691 |         status.addresult("BBPATH references the current directory, either through "    \ | 
 | 692 |                 "an empty entry, a './' or a '.'.\n\t This is unsafe and means your "\ | 
 | 693 |                 "layer configuration is adding empty elements to BBPATH.\n\t "\ | 
 | 694 |                 "Please check your layer.conf files and other BBPATH "        \ | 
 | 695 |                 "settings to remove the current working directory "           \ | 
 | 696 |                 "references.\n" \ | 
 | 697 |                 "Parsed BBPATH is" + str(bbpaths)); | 
 | 698 |  | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 699 |     oes_bb_conf = d.getVar( 'OES_BITBAKE_CONF') | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 700 |     if not oes_bb_conf: | 
 | 701 |         status.addresult('You are not using the OpenEmbedded version of conf/bitbake.conf. This means your environment is misconfigured, in particular check BBPATH.\n') | 
 | 702 |  | 
 | 703 |     # The length of TMPDIR can't be longer than 410 | 
 | 704 |     status.addresult(check_path_length(tmpdir, "TMPDIR", 410)) | 
 | 705 |  | 
 | 706 |     # Check that TMPDIR isn't located on nfs | 
 | 707 |     status.addresult(check_not_nfs(tmpdir, "TMPDIR")) | 
 | 708 |  | 
| Brad Bishop | d7bf8c1 | 2018-02-25 22:55:05 -0500 | [diff] [blame] | 709 |     # Check for case-insensitive file systems (such as Linux in Docker on | 
 | 710 |     # macOS with default HFS+ file system) | 
 | 711 |     status.addresult(check_case_sensitive(tmpdir, "TMPDIR")) | 
 | 712 |  | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 713 | def sanity_check_locale(d): | 
 | 714 |     """ | 
 | 715 |     Currently bitbake switches locale to en_US.UTF-8 so check that this locale actually exists. | 
 | 716 |     """ | 
 | 717 |     import locale | 
 | 718 |     try: | 
 | 719 |         locale.setlocale(locale.LC_ALL, "en_US.UTF-8") | 
 | 720 |     except locale.Error: | 
| Brad Bishop | 316dfdd | 2018-06-25 12:45:53 -0400 | [diff] [blame] | 721 |         raise_sanity_error("Your system needs to support the en_US.UTF-8 locale.", d) | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 722 |  | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 723 | def check_sanity_everybuild(status, d): | 
 | 724 |     import os, stat | 
 | 725 |     # Sanity tests which test the users environment so need to run at each build (or are so cheap | 
 | 726 |     # it makes sense to always run them. | 
 | 727 |  | 
 | 728 |     if 0 == os.getuid(): | 
 | 729 |         raise_sanity_error("Do not use Bitbake as root.", d) | 
 | 730 |  | 
| Brad Bishop | d7bf8c1 | 2018-02-25 22:55:05 -0500 | [diff] [blame] | 731 |     # Check the Python version, we now have a minimum of Python 3.4 | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 732 |     import sys | 
| Brad Bishop | d7bf8c1 | 2018-02-25 22:55:05 -0500 | [diff] [blame] | 733 |     if sys.hexversion < 0x03040000: | 
 | 734 |         status.addresult('The system requires at least Python 3.4 to run. Please update your Python interpreter.\n') | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 735 |  | 
 | 736 |     # Check the bitbake version meets minimum requirements | 
 | 737 |     from distutils.version import LooseVersion | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 738 |     minversion = d.getVar('BB_MIN_VERSION') | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 739 |     if (LooseVersion(bb.__version__) < LooseVersion(minversion)): | 
 | 740 |         status.addresult('Bitbake version %s is required and version %s was found\n' % (minversion, bb.__version__)) | 
 | 741 |  | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 742 |     sanity_check_locale(d) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 743 |  | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 744 |     paths = d.getVar('PATH').split(":") | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 745 |     if "." in paths or "./" in paths or "" in paths: | 
 | 746 |         status.addresult("PATH contains '.', './' or '' (empty element), which will break the build, please remove this.\nParsed PATH is " + str(paths) + "\n") | 
 | 747 |  | 
 | 748 |     # Check that the DISTRO is valid, if set | 
 | 749 |     # need to take into account DISTRO renaming DISTRO | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 750 |     distro = d.getVar('DISTRO') | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 751 |     if distro and distro != "nodistro": | 
 | 752 |         if not ( check_conf_exists("conf/distro/${DISTRO}.conf", d) or check_conf_exists("conf/distro/include/${DISTRO}.inc", d) ): | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 753 |             status.addresult("DISTRO '%s' not found. Please set a valid DISTRO in your local.conf\n" % d.getVar("DISTRO")) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 754 |  | 
| Brad Bishop | d7bf8c1 | 2018-02-25 22:55:05 -0500 | [diff] [blame] | 755 |     # Check that these variables don't use tilde-expansion as we don't do that | 
 | 756 |     for v in ("TMPDIR", "DL_DIR", "SSTATE_DIR"): | 
 | 757 |         if d.getVar(v).startswith("~"): | 
 | 758 |             status.addresult("%s uses ~ but Bitbake will not expand this, use an absolute path or variables." % v) | 
 | 759 |  | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 760 |     # Check that DL_DIR is set, exists and is writable. In theory, we should never even hit the check if DL_DIR isn't  | 
 | 761 |     # set, since so much relies on it being set. | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 762 |     dldir = d.getVar('DL_DIR') | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 763 |     if not dldir: | 
 | 764 |         status.addresult("DL_DIR is not set. Your environment is misconfigured, check that DL_DIR is set, and if the directory exists, that it is writable. \n") | 
 | 765 |     if os.path.exists(dldir) and not os.access(dldir, os.W_OK): | 
 | 766 |         status.addresult("DL_DIR: %s exists but you do not appear to have write access to it. \n" % dldir) | 
 | 767 |     check_symlink(dldir, d) | 
 | 768 |  | 
 | 769 |     # Check that the MACHINE is valid, if it is set | 
 | 770 |     machinevalid = True | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 771 |     if d.getVar('MACHINE'): | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 772 |         if not check_conf_exists("conf/machine/${MACHINE}.conf", d): | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 773 |             status.addresult('MACHINE=%s is invalid. Please set a valid MACHINE in your local.conf, environment or other configuration file.\n' % (d.getVar('MACHINE'))) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 774 |             machinevalid = False | 
 | 775 |         else: | 
 | 776 |             status.addresult(check_sanity_validmachine(d)) | 
 | 777 |     else: | 
 | 778 |         status.addresult('Please set a MACHINE in your local.conf or environment\n') | 
 | 779 |         machinevalid = False | 
 | 780 |     if machinevalid: | 
 | 781 |         status.addresult(check_toolchain(d)) | 
 | 782 |  | 
 | 783 |     # Check that the SDKMACHINE is valid, if it is set | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 784 |     if d.getVar('SDKMACHINE'): | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 785 |         if not check_conf_exists("conf/machine-sdk/${SDKMACHINE}.conf", d): | 
 | 786 |             status.addresult('Specified SDKMACHINE value is not valid\n') | 
 | 787 |         elif d.getVar('SDK_ARCH', False) == "${BUILD_ARCH}": | 
 | 788 |             status.addresult('SDKMACHINE is set, but SDK_ARCH has not been changed as a result - SDKMACHINE may have been set too late (e.g. in the distro configuration)\n') | 
 | 789 |  | 
 | 790 |     check_supported_distro(d) | 
 | 791 |  | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 792 |     omask = os.umask(0o022) | 
 | 793 |     if omask & 0o755: | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 794 |         status.addresult("Please use a umask which allows a+rx and u+rwx\n") | 
 | 795 |     os.umask(omask) | 
 | 796 |  | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 797 |     if d.getVar('TARGET_ARCH') == "arm": | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 798 |         # This path is no longer user-readable in modern (very recent) Linux | 
 | 799 |         try: | 
 | 800 |             if os.path.exists("/proc/sys/vm/mmap_min_addr"): | 
 | 801 |                 f = open("/proc/sys/vm/mmap_min_addr", "r") | 
 | 802 |                 try: | 
 | 803 |                     if (int(f.read().strip()) > 65536): | 
 | 804 |                         status.addresult("/proc/sys/vm/mmap_min_addr is not <= 65536. This will cause problems with qemu so please fix the value (as root).\n\nTo fix this in later reboots, set vm.mmap_min_addr = 65536 in /etc/sysctl.conf.\n") | 
 | 805 |                 finally: | 
 | 806 |                     f.close() | 
 | 807 |         except: | 
 | 808 |             pass | 
 | 809 |  | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 810 |     oeroot = d.getVar('COREBASE') | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 811 |     if oeroot.find('+') != -1: | 
 | 812 |         status.addresult("Error, you have an invalid character (+) in your COREBASE directory path. Please move the installation to a directory which doesn't include any + characters.") | 
 | 813 |     if oeroot.find('@') != -1: | 
 | 814 |         status.addresult("Error, you have an invalid character (@) in your COREBASE directory path. Please move the installation to a directory which doesn't include any @ characters.") | 
 | 815 |     if oeroot.find(' ') != -1: | 
 | 816 |         status.addresult("Error, you have a space in your COREBASE directory path. Please move the installation to a directory which doesn't include a space since autotools doesn't support this.") | 
 | 817 |  | 
 | 818 |     # Check the format of MIRRORS, PREMIRRORS and SSTATE_MIRRORS | 
 | 819 |     import re | 
 | 820 |     mirror_vars = ['MIRRORS', 'PREMIRRORS', 'SSTATE_MIRRORS'] | 
 | 821 |     protocols = ['http', 'ftp', 'file', 'https', \ | 
 | 822 |                  'git', 'gitsm', 'hg', 'osc', 'p4', 'svn', \ | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 823 |                  'bzr', 'cvs', 'npm', 'sftp', 'ssh', 's3' ] | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 824 |     for mirror_var in mirror_vars: | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 825 |         mirrors = (d.getVar(mirror_var) or '').replace('\\n', ' ').split() | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 826 |  | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 827 |         # Split into pairs | 
 | 828 |         if len(mirrors) % 2 != 0: | 
| Brad Bishop | d7bf8c1 | 2018-02-25 22:55:05 -0500 | [diff] [blame] | 829 |             bb.warn('Invalid mirror variable value for %s: %s, should contain paired members.' % (mirror_var, str(mirrors))) | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 830 |             continue | 
 | 831 |         mirrors = list(zip(*[iter(mirrors)]*2)) | 
 | 832 |  | 
 | 833 |         for mirror_entry in mirrors: | 
 | 834 |             pattern, mirror = mirror_entry | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 835 |  | 
 | 836 |             decoded = bb.fetch2.decodeurl(pattern) | 
 | 837 |             try: | 
 | 838 |                 pattern_scheme = re.compile(decoded[0]) | 
 | 839 |             except re.error as exc: | 
 | 840 |                 bb.warn('Invalid scheme regex (%s) in %s; %s' % (pattern, mirror_var, mirror_entry)) | 
 | 841 |                 continue | 
 | 842 |  | 
 | 843 |             if not any(pattern_scheme.match(protocol) for protocol in protocols): | 
 | 844 |                 bb.warn('Invalid protocol (%s) in %s: %s' % (decoded[0], mirror_var, mirror_entry)) | 
 | 845 |                 continue | 
 | 846 |  | 
 | 847 |             if not any(mirror.startswith(protocol + '://') for protocol in protocols): | 
 | 848 |                 bb.warn('Invalid protocol in %s: %s' % (mirror_var, mirror_entry)) | 
 | 849 |                 continue | 
 | 850 |  | 
 | 851 |             if mirror.startswith('file://'): | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 852 |                 import urllib | 
 | 853 |                 check_symlink(urllib.parse.urlparse(mirror).path, d) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 854 |                 # SSTATE_MIRROR ends with a /PATH string | 
 | 855 |                 if mirror.endswith('/PATH'): | 
 | 856 |                     # remove /PATH$ from SSTATE_MIRROR to get a working | 
 | 857 |                     # base directory path | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 858 |                     mirror_base = urllib.parse.urlparse(mirror[:-1*len('/PATH')]).path | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 859 |                     check_symlink(mirror_base, d) | 
 | 860 |  | 
 | 861 |     # Check that TMPDIR hasn't changed location since the last time we were run | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 862 |     tmpdir = d.getVar('TMPDIR') | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 863 |     checkfile = os.path.join(tmpdir, "saved_tmpdir") | 
 | 864 |     if os.path.exists(checkfile): | 
 | 865 |         with open(checkfile, "r") as f: | 
 | 866 |             saved_tmpdir = f.read().strip() | 
 | 867 |             if (saved_tmpdir != tmpdir): | 
 | 868 |                 status.addresult("Error, TMPDIR has changed location. You need to either move it back to %s or rebuild\n" % saved_tmpdir) | 
 | 869 |     else: | 
 | 870 |         bb.utils.mkdirhier(tmpdir) | 
 | 871 |         # Remove setuid, setgid and sticky bits from TMPDIR | 
| Patrick Williams | f1e5d69 | 2016-03-30 15:21:19 -0500 | [diff] [blame] | 872 |         try: | 
 | 873 |             os.chmod(tmpdir, os.stat(tmpdir).st_mode & ~ stat.S_ISUID) | 
 | 874 |             os.chmod(tmpdir, os.stat(tmpdir).st_mode & ~ stat.S_ISGID) | 
 | 875 |             os.chmod(tmpdir, os.stat(tmpdir).st_mode & ~ stat.S_ISVTX) | 
 | 876 |         except OSError as exc: | 
 | 877 |             bb.warn("Unable to chmod TMPDIR: %s" % exc) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 878 |         with open(checkfile, "w") as f: | 
 | 879 |             f.write(tmpdir) | 
 | 880 |  | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 881 |     # If /bin/sh is a symlink, check that it points to dash or bash | 
 | 882 |     if os.path.islink('/bin/sh'): | 
 | 883 |         real_sh = os.path.realpath('/bin/sh') | 
| Brad Bishop | 37a0e4d | 2017-12-04 01:01:44 -0500 | [diff] [blame] | 884 |         # Due to update-alternatives, the shell name may take various | 
 | 885 |         # forms, such as /bin/dash, bin/bash, /bin/bash.bash ... | 
 | 886 |         if '/dash' not in real_sh and '/bash' not in real_sh: | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 887 |             status.addresult("Error, /bin/sh links to %s, must be dash or bash\n" % real_sh) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 888 |  | 
 | 889 | def check_sanity(sanity_data): | 
 | 890 |     class SanityStatus(object): | 
 | 891 |         def __init__(self): | 
 | 892 |             self.messages = "" | 
 | 893 |             self.network_error = False | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 894 |  | 
 | 895 |         def addresult(self, message): | 
 | 896 |             if message: | 
 | 897 |                 self.messages = self.messages + message | 
 | 898 |  | 
 | 899 |     status = SanityStatus() | 
 | 900 |  | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 901 |     tmpdir = sanity_data.getVar('TMPDIR') | 
 | 902 |     sstate_dir = sanity_data.getVar('SSTATE_DIR') | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 903 |  | 
 | 904 |     check_symlink(sstate_dir, sanity_data) | 
 | 905 |  | 
 | 906 |     # Check saved sanity info | 
 | 907 |     last_sanity_version = 0 | 
 | 908 |     last_tmpdir = "" | 
 | 909 |     last_sstate_dir = "" | 
| Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 910 |     last_nativelsbstr = "" | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 911 |     sanityverfile = sanity_data.expand("${TOPDIR}/conf/sanity_info") | 
 | 912 |     if os.path.exists(sanityverfile): | 
 | 913 |         with open(sanityverfile, 'r') as f: | 
 | 914 |             for line in f: | 
 | 915 |                 if line.startswith('SANITY_VERSION'): | 
 | 916 |                     last_sanity_version = int(line.split()[1]) | 
 | 917 |                 if line.startswith('TMPDIR'): | 
 | 918 |                     last_tmpdir = line.split()[1] | 
 | 919 |                 if line.startswith('SSTATE_DIR'): | 
 | 920 |                     last_sstate_dir = line.split()[1] | 
| Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 921 |                 if line.startswith('NATIVELSBSTRING'): | 
 | 922 |                     last_nativelsbstr = line.split()[1] | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 923 |  | 
 | 924 |     check_sanity_everybuild(status, sanity_data) | 
 | 925 |      | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 926 |     sanity_version = int(sanity_data.getVar('SANITY_VERSION') or 1) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 927 |     network_error = False | 
| Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 928 |     # NATIVELSBSTRING var may have been overridden with "universal", so | 
 | 929 |     # get actual host distribution id and version | 
 | 930 |     nativelsbstr = lsb_distro_identifier(sanity_data) | 
 | 931 |     if last_sanity_version < sanity_version or last_nativelsbstr != nativelsbstr:  | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 932 |         check_sanity_version_change(status, sanity_data) | 
 | 933 |         status.addresult(check_sanity_sstate_dir_change(sstate_dir, sanity_data)) | 
 | 934 |     else:  | 
 | 935 |         if last_sstate_dir != sstate_dir: | 
 | 936 |             status.addresult(check_sanity_sstate_dir_change(sstate_dir, sanity_data)) | 
 | 937 |  | 
 | 938 |     if os.path.exists(os.path.dirname(sanityverfile)) and not status.messages: | 
 | 939 |         with open(sanityverfile, 'w') as f: | 
 | 940 |             f.write("SANITY_VERSION %s\n" % sanity_version)  | 
 | 941 |             f.write("TMPDIR %s\n" % tmpdir)  | 
 | 942 |             f.write("SSTATE_DIR %s\n" % sstate_dir)  | 
| Patrick Williams | d8c66bc | 2016-06-20 12:57:21 -0500 | [diff] [blame] | 943 |             f.write("NATIVELSBSTRING %s\n" % nativelsbstr)  | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 944 |  | 
 | 945 |     sanity_handle_abichanges(status, sanity_data) | 
 | 946 |  | 
 | 947 |     if status.messages != "": | 
 | 948 |         raise_sanity_error(sanity_data.expand(status.messages), sanity_data, status.network_error) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 949 |  | 
 | 950 | # Create a copy of the datastore and finalise it to ensure appends and  | 
 | 951 | # overrides are set - the datastore has yet to be finalised at ConfigParsed | 
 | 952 | def copy_data(e): | 
 | 953 |     sanity_data = bb.data.createCopy(e.data) | 
 | 954 |     sanity_data.finalize() | 
 | 955 |     return sanity_data | 
 | 956 |  | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 957 | addhandler config_reparse_eventhandler | 
 | 958 | config_reparse_eventhandler[eventmask] = "bb.event.ConfigParsed" | 
 | 959 | python config_reparse_eventhandler() { | 
 | 960 |     sanity_check_conffiles(e.data) | 
 | 961 | } | 
 | 962 |  | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 963 | addhandler check_sanity_eventhandler | 
 | 964 | check_sanity_eventhandler[eventmask] = "bb.event.SanityCheck bb.event.NetworkTest" | 
 | 965 | python check_sanity_eventhandler() { | 
 | 966 |     if bb.event.getName(e) == "SanityCheck": | 
 | 967 |         sanity_data = copy_data(e) | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 968 |         check_sanity(sanity_data) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 969 |         if e.generateevents: | 
 | 970 |             sanity_data.setVar("SANITY_USE_EVENTS", "1") | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 971 |         bb.event.fire(bb.event.SanityCheckPassed(), e.data) | 
 | 972 |     elif bb.event.getName(e) == "NetworkTest": | 
 | 973 |         sanity_data = copy_data(e) | 
 | 974 |         if e.generateevents: | 
 | 975 |             sanity_data.setVar("SANITY_USE_EVENTS", "1") | 
 | 976 |         bb.event.fire(bb.event.NetworkTestFailed() if check_connectivity(sanity_data) else bb.event.NetworkTestPassed(), e.data) | 
 | 977 |  | 
 | 978 |     return | 
 | 979 | } |