diff options
| author | Richard Purdie <richard.purdie@linuxfoundation.org> | 2022-11-24 22:10:40 +0000 |
|---|---|---|
| committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2023-01-05 11:52:50 +0000 |
| commit | ed07d52b476a22959cdd1c61d1c396345f996bbf (patch) | |
| tree | e40a1d120058b4d474def57ca9b0e8e924aea212 /meta/lib | |
| parent | a19687acd12497d727203e63d74b2703387f34a6 (diff) | |
| download | poky-ed07d52b476a22959cdd1c61d1c396345f996bbf.tar.gz | |
package: Move fixup_perms function to bb function library
To avoid reparsing the bbclass code all the time, move the function
to the python function library code which is more efficient.
(From OE-Core rev: 7c8c4cfd9355a9cee1144e0444e1b54402f1951c)
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/lib')
| -rw-r--r-- | meta/lib/oe/package.py | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/meta/lib/oe/package.py b/meta/lib/oe/package.py index 4aa40d70ee..05447f8808 100644 --- a/meta/lib/oe/package.py +++ b/meta/lib/oe/package.py | |||
| @@ -292,3 +292,245 @@ def read_shlib_providers(d): | |||
| 292 | shlib_provider[s[0]] = {} | 292 | shlib_provider[s[0]] = {} |
| 293 | shlib_provider[s[0]][s[1]] = (dep_pkg, s[2]) | 293 | shlib_provider[s[0]][s[1]] = (dep_pkg, s[2]) |
| 294 | return shlib_provider | 294 | return shlib_provider |
| 295 | |||
| 296 | # We generate a master list of directories to process, we start by | ||
| 297 | # seeding this list with reasonable defaults, then load from | ||
| 298 | # the fs-perms.txt files | ||
| 299 | def fixup_perms(d): | ||
| 300 | import pwd, grp | ||
| 301 | import oe.cachedpath | ||
| 302 | |||
| 303 | cpath = oe.cachedpath.CachedPath() | ||
| 304 | dvar = d.getVar('PKGD') | ||
| 305 | |||
| 306 | # init using a string with the same format as a line as documented in | ||
| 307 | # the fs-perms.txt file | ||
| 308 | # <path> <mode> <uid> <gid> <walk> <fmode> <fuid> <fgid> | ||
| 309 | # <path> link <link target> | ||
| 310 | # | ||
| 311 | # __str__ can be used to print out an entry in the input format | ||
| 312 | # | ||
| 313 | # if fs_perms_entry.path is None: | ||
| 314 | # an error occurred | ||
| 315 | # if fs_perms_entry.link, you can retrieve: | ||
| 316 | # fs_perms_entry.path = path | ||
| 317 | # fs_perms_entry.link = target of link | ||
| 318 | # if not fs_perms_entry.link, you can retrieve: | ||
| 319 | # fs_perms_entry.path = path | ||
| 320 | # fs_perms_entry.mode = expected dir mode or None | ||
| 321 | # fs_perms_entry.uid = expected uid or -1 | ||
| 322 | # fs_perms_entry.gid = expected gid or -1 | ||
| 323 | # fs_perms_entry.walk = 'true' or something else | ||
| 324 | # fs_perms_entry.fmode = expected file mode or None | ||
| 325 | # fs_perms_entry.fuid = expected file uid or -1 | ||
| 326 | # fs_perms_entry_fgid = expected file gid or -1 | ||
| 327 | class fs_perms_entry(): | ||
| 328 | def __init__(self, line): | ||
| 329 | lsplit = line.split() | ||
| 330 | if len(lsplit) == 3 and lsplit[1].lower() == "link": | ||
| 331 | self._setlink(lsplit[0], lsplit[2]) | ||
| 332 | elif len(lsplit) == 8: | ||
| 333 | self._setdir(lsplit[0], lsplit[1], lsplit[2], lsplit[3], lsplit[4], lsplit[5], lsplit[6], lsplit[7]) | ||
| 334 | else: | ||
| 335 | msg = "Fixup Perms: invalid config line %s" % line | ||
| 336 | oe.qa.handle_error("perm-config", msg, d) | ||
| 337 | self.path = None | ||
| 338 | self.link = None | ||
| 339 | |||
| 340 | def _setdir(self, path, mode, uid, gid, walk, fmode, fuid, fgid): | ||
| 341 | self.path = os.path.normpath(path) | ||
| 342 | self.link = None | ||
| 343 | self.mode = self._procmode(mode) | ||
| 344 | self.uid = self._procuid(uid) | ||
| 345 | self.gid = self._procgid(gid) | ||
| 346 | self.walk = walk.lower() | ||
| 347 | self.fmode = self._procmode(fmode) | ||
| 348 | self.fuid = self._procuid(fuid) | ||
| 349 | self.fgid = self._procgid(fgid) | ||
| 350 | |||
| 351 | def _setlink(self, path, link): | ||
| 352 | self.path = os.path.normpath(path) | ||
| 353 | self.link = link | ||
| 354 | |||
| 355 | def _procmode(self, mode): | ||
| 356 | if not mode or (mode and mode == "-"): | ||
| 357 | return None | ||
| 358 | else: | ||
| 359 | return int(mode,8) | ||
| 360 | |||
| 361 | # Note uid/gid -1 has special significance in os.lchown | ||
| 362 | def _procuid(self, uid): | ||
| 363 | if uid is None or uid == "-": | ||
| 364 | return -1 | ||
| 365 | elif uid.isdigit(): | ||
| 366 | return int(uid) | ||
| 367 | else: | ||
| 368 | return pwd.getpwnam(uid).pw_uid | ||
| 369 | |||
| 370 | def _procgid(self, gid): | ||
| 371 | if gid is None or gid == "-": | ||
| 372 | return -1 | ||
| 373 | elif gid.isdigit(): | ||
| 374 | return int(gid) | ||
| 375 | else: | ||
| 376 | return grp.getgrnam(gid).gr_gid | ||
| 377 | |||
| 378 | # Use for debugging the entries | ||
| 379 | def __str__(self): | ||
| 380 | if self.link: | ||
| 381 | return "%s link %s" % (self.path, self.link) | ||
| 382 | else: | ||
| 383 | mode = "-" | ||
| 384 | if self.mode: | ||
| 385 | mode = "0%o" % self.mode | ||
| 386 | fmode = "-" | ||
| 387 | if self.fmode: | ||
| 388 | fmode = "0%o" % self.fmode | ||
| 389 | uid = self._mapugid(self.uid) | ||
| 390 | gid = self._mapugid(self.gid) | ||
| 391 | fuid = self._mapugid(self.fuid) | ||
| 392 | fgid = self._mapugid(self.fgid) | ||
| 393 | return "%s %s %s %s %s %s %s %s" % (self.path, mode, uid, gid, self.walk, fmode, fuid, fgid) | ||
| 394 | |||
| 395 | def _mapugid(self, id): | ||
| 396 | if id is None or id == -1: | ||
| 397 | return "-" | ||
| 398 | else: | ||
| 399 | return "%d" % id | ||
| 400 | |||
| 401 | # Fix the permission, owner and group of path | ||
| 402 | def fix_perms(path, mode, uid, gid, dir): | ||
| 403 | if mode and not os.path.islink(path): | ||
| 404 | #bb.note("Fixup Perms: chmod 0%o %s" % (mode, dir)) | ||
| 405 | os.chmod(path, mode) | ||
| 406 | # -1 is a special value that means don't change the uid/gid | ||
| 407 | # if they are BOTH -1, don't bother to lchown | ||
| 408 | if not (uid == -1 and gid == -1): | ||
| 409 | #bb.note("Fixup Perms: lchown %d:%d %s" % (uid, gid, dir)) | ||
| 410 | os.lchown(path, uid, gid) | ||
| 411 | |||
| 412 | # Return a list of configuration files based on either the default | ||
| 413 | # files/fs-perms.txt or the contents of FILESYSTEM_PERMS_TABLES | ||
| 414 | # paths are resolved via BBPATH | ||
| 415 | def get_fs_perms_list(d): | ||
| 416 | str = "" | ||
| 417 | bbpath = d.getVar('BBPATH') | ||
| 418 | fs_perms_tables = d.getVar('FILESYSTEM_PERMS_TABLES') or "" | ||
| 419 | for conf_file in fs_perms_tables.split(): | ||
| 420 | confpath = bb.utils.which(bbpath, conf_file) | ||
| 421 | if confpath: | ||
| 422 | str += " %s" % bb.utils.which(bbpath, conf_file) | ||
| 423 | else: | ||
| 424 | bb.warn("cannot find %s specified in FILESYSTEM_PERMS_TABLES" % conf_file) | ||
| 425 | return str | ||
| 426 | |||
| 427 | fs_perms_table = {} | ||
| 428 | fs_link_table = {} | ||
| 429 | |||
| 430 | # By default all of the standard directories specified in | ||
| 431 | # bitbake.conf will get 0755 root:root. | ||
| 432 | target_path_vars = [ 'base_prefix', | ||
| 433 | 'prefix', | ||
| 434 | 'exec_prefix', | ||
| 435 | 'base_bindir', | ||
| 436 | 'base_sbindir', | ||
| 437 | 'base_libdir', | ||
| 438 | 'datadir', | ||
| 439 | 'sysconfdir', | ||
| 440 | 'servicedir', | ||
| 441 | 'sharedstatedir', | ||
| 442 | 'localstatedir', | ||
| 443 | 'infodir', | ||
| 444 | 'mandir', | ||
| 445 | 'docdir', | ||
| 446 | 'bindir', | ||
| 447 | 'sbindir', | ||
| 448 | 'libexecdir', | ||
| 449 | 'libdir', | ||
| 450 | 'includedir', | ||
| 451 | 'oldincludedir' ] | ||
| 452 | |||
| 453 | for path in target_path_vars: | ||
| 454 | dir = d.getVar(path) or "" | ||
| 455 | if dir == "": | ||
| 456 | continue | ||
| 457 | fs_perms_table[dir] = fs_perms_entry(d.expand("%s 0755 root root false - - -" % (dir))) | ||
| 458 | |||
| 459 | # Now we actually load from the configuration files | ||
| 460 | for conf in get_fs_perms_list(d).split(): | ||
| 461 | if not os.path.exists(conf): | ||
| 462 | continue | ||
| 463 | with open(conf) as f: | ||
| 464 | for line in f: | ||
| 465 | if line.startswith('#'): | ||
| 466 | continue | ||
| 467 | lsplit = line.split() | ||
| 468 | if len(lsplit) == 0: | ||
| 469 | continue | ||
| 470 | if len(lsplit) != 8 and not (len(lsplit) == 3 and lsplit[1].lower() == "link"): | ||
| 471 | msg = "Fixup perms: %s invalid line: %s" % (conf, line) | ||
| 472 | oe.qa.handle_error("perm-line", msg, d) | ||
| 473 | continue | ||
| 474 | entry = fs_perms_entry(d.expand(line)) | ||
| 475 | if entry and entry.path: | ||
| 476 | if entry.link: | ||
| 477 | fs_link_table[entry.path] = entry | ||
| 478 | if entry.path in fs_perms_table: | ||
| 479 | fs_perms_table.pop(entry.path) | ||
| 480 | else: | ||
| 481 | fs_perms_table[entry.path] = entry | ||
| 482 | if entry.path in fs_link_table: | ||
| 483 | fs_link_table.pop(entry.path) | ||
| 484 | |||
| 485 | # Debug -- list out in-memory table | ||
| 486 | #for dir in fs_perms_table: | ||
| 487 | # bb.note("Fixup Perms: %s: %s" % (dir, str(fs_perms_table[dir]))) | ||
| 488 | #for link in fs_link_table: | ||
| 489 | # bb.note("Fixup Perms: %s: %s" % (link, str(fs_link_table[link]))) | ||
| 490 | |||
| 491 | # We process links first, so we can go back and fixup directory ownership | ||
| 492 | # for any newly created directories | ||
| 493 | # Process in sorted order so /run gets created before /run/lock, etc. | ||
| 494 | for entry in sorted(fs_link_table.values(), key=lambda x: x.link): | ||
| 495 | link = entry.link | ||
| 496 | dir = entry.path | ||
| 497 | origin = dvar + dir | ||
| 498 | if not (cpath.exists(origin) and cpath.isdir(origin) and not cpath.islink(origin)): | ||
| 499 | continue | ||
| 500 | |||
| 501 | if link[0] == "/": | ||
| 502 | target = dvar + link | ||
| 503 | ptarget = link | ||
| 504 | else: | ||
| 505 | target = os.path.join(os.path.dirname(origin), link) | ||
| 506 | ptarget = os.path.join(os.path.dirname(dir), link) | ||
| 507 | if os.path.exists(target): | ||
| 508 | msg = "Fixup Perms: Unable to correct directory link, target already exists: %s -> %s" % (dir, ptarget) | ||
| 509 | oe.qa.handle_error("perm-link", msg, d) | ||
| 510 | continue | ||
| 511 | |||
| 512 | # Create path to move directory to, move it, and then setup the symlink | ||
| 513 | bb.utils.mkdirhier(os.path.dirname(target)) | ||
| 514 | #bb.note("Fixup Perms: Rename %s -> %s" % (dir, ptarget)) | ||
| 515 | bb.utils.rename(origin, target) | ||
| 516 | #bb.note("Fixup Perms: Link %s -> %s" % (dir, link)) | ||
| 517 | os.symlink(link, origin) | ||
| 518 | |||
| 519 | for dir in fs_perms_table: | ||
| 520 | origin = dvar + dir | ||
| 521 | if not (cpath.exists(origin) and cpath.isdir(origin)): | ||
| 522 | continue | ||
| 523 | |||
| 524 | fix_perms(origin, fs_perms_table[dir].mode, fs_perms_table[dir].uid, fs_perms_table[dir].gid, dir) | ||
| 525 | |||
| 526 | if fs_perms_table[dir].walk == 'true': | ||
| 527 | for root, dirs, files in os.walk(origin): | ||
| 528 | for dr in dirs: | ||
| 529 | each_dir = os.path.join(root, dr) | ||
| 530 | fix_perms(each_dir, fs_perms_table[dir].mode, fs_perms_table[dir].uid, fs_perms_table[dir].gid, dir) | ||
| 531 | for f in files: | ||
| 532 | each_file = os.path.join(root, f) | ||
| 533 | fix_perms(each_file, fs_perms_table[dir].fmode, fs_perms_table[dir].fuid, fs_perms_table[dir].fgid, dir) | ||
| 534 | |||
| 535 | |||
| 536 | |||
