[Notes] [Git][BuildStream/buildstream][valentindavid/link_files_sort_resolved] Fix issue with absolute symbolic links in copy_files/link_files



Title: GitLab

Valentin David pushed to branch valentindavid/link_files_sort_resolved at BuildStream / buildstream

Commits:

6 changed files:

Changes:

  • buildstream/utils.py
    ... ... @@ -743,6 +743,48 @@ def _ensure_real_directory(root, destpath):
    743 743
         return destpath_resolved
    
    744 744
     
    
    745 745
     
    
    746
    +@functools.lru_cache(maxsize=1)
    
    747
    +def _symloop_max():
    
    748
    +    if hasattr(os, 'sysconf'):
    
    749
    +        try:
    
    750
    +            ret = os.sysconf('_SC_SYMLOOP_MAX')
    
    751
    +            if ret != -1:
    
    752
    +                return ret
    
    753
    +        except ValueError:
    
    754
    +            pass
    
    755
    +    return 8
    
    756
    +
    
    757
    +
    
    758
    +@functools.lru_cache(maxsize=64)
    
    759
    +def _sysroot_realpath(path, sysroot):
    
    760
    +    assert not os.path.isabs(path)
    
    761
    +    assert os.path.isabs(sysroot)
    
    762
    +
    
    763
    +    loop_count = _symloop_max()
    
    764
    +    while True:
    
    765
    +        full_path = os.path.join(sysroot, path)
    
    766
    +        st = os.lstat(full_path)
    
    767
    +        mode = st.st_mode
    
    768
    +        if not stat.S_ISLNK(mode):
    
    769
    +            break
    
    770
    +        loop_count = loop_count - 1
    
    771
    +        if loop_count < 0:
    
    772
    +            raise UtilError("Symlink loop detected: {}".format(os.path.join(sysroot, path)))
    
    773
    +        link_path = os.readlink(full_path)
    
    774
    +        if not os.path.isabs(link_path):
    
    775
    +            link_path = os.path.join('/', os.path.dirname(path), link_path)
    
    776
    +        path = os.path.relpath(os.path.normpath(link_path), '/')
    
    777
    +
    
    778
    +    parent = os.path.dirname(path)
    
    779
    +    if parent != '':
    
    780
    +        parent = _sysroot_realpath(parent, sysroot)
    
    781
    +        full_parent = os.path.join(sysroot, parent)
    
    782
    +        if not os.path.isdir(full_parent):
    
    783
    +            raise UtilError("Path is not a directory: {}".format(full_parent))
    
    784
    +
    
    785
    +    return os.path.join(parent, os.path.basename(path))
    
    786
    +
    
    787
    +
    
    746 788
     # _process_list()
    
    747 789
     #
    
    748 790
     # Internal helper for copying/moving/linking file lists
    
    ... ... @@ -773,10 +815,10 @@ def _process_list(srcdir, destdir, filelist, actionfunc, result,
    773 815
         # those directories.
    
    774 816
         if not presorted:
    
    775 817
             resolved = []
    
    818
    +        _sysroot_realpath.cache_clear()
    
    776 819
             for f in filelist:
    
    777 820
                 dirname = os.path.dirname(f)
    
    778
    -            dirname = os.path.realpath(os.path.join(srcdir, dirname))
    
    779
    -            dirname = os.path.relpath(dirname, srcdir)
    
    821
    +            dirname = _sysroot_realpath(dirname, srcdir)
    
    780 822
                 if dirname == '.':
    
    781 823
                     resolved.append(os.path.basename(f))
    
    782 824
                 else:
    

  • tests/integration/compose-symlinks.py
    ... ... @@ -41,3 +41,18 @@ def test_compose_symlinks(cli, tmpdir, datafiles):
    41 41
     
    
    42 42
         assert set(walk_dir(checkout)) == set(['/sbin', '/usr', '/usr/sbin',
    
    43 43
                                                '/usr/sbin/init', '/usr/sbin/dummy'])
    
    44
    +
    
    45
    +
    
    46
    +@pytest.mark.datafiles(DATA_DIR)
    
    47
    +def test_compose_absolute_symlinks(cli, tmpdir, datafiles):
    
    48
    +    project = str(datafiles)
    
    49
    +    checkout = os.path.join(cli.directory, 'checkout')
    
    50
    +    element_path = os.path.join(project, 'elements')
    
    51
    +
    
    52
    +    result = cli.run(project=project, args=['build', 'compose-symlinks/compose-absolute-symlink.bst'])
    
    53
    +    result.assert_success()
    
    54
    +
    
    55
    +    result = cli.run(project=project, args=['checkout', 'compose-symlinks/compose-absolute-symlink.bst', checkout])
    
    56
    +    result.assert_success()
    
    57
    +
    
    58
    +    assert os.readlink(os.path.join(checkout, 'foo')) == 'test/foo'

  • tests/integration/project/elements/compose-symlinks/a-foo-symlink.bst
    1
    +kind: script
    
    2
    +
    
    3
    +depends:
    
    4
    +- filename: base.bst
    
    5
    +  type: build
    
    6
    +
    
    7
    +config:
    
    8
    +  commands:
    
    9
    +  - |
    
    10
    +    mkdir -p "%{install-root}/bar"
    
    11
    +    ln -s "/bar" "%{install-root}/foo"

  • tests/integration/project/elements/compose-symlinks/compose-absolute-symlink.bst
    1
    +kind: compose
    
    2
    +
    
    3
    +depends:
    
    4
    +- filename: compose-symlinks/foo-dir.bst
    
    5
    +  type: build
    
    6
    +- filename: compose-symlinks/a-foo-symlink.bst
    
    7
    +  type: build
    
    8
    +- filename: compose-symlinks/integration-move-dir.bst
    
    9
    +  type: build
    
    10
    +
    
    11
    +config:
    
    12
    +  include-orphans: true
    
    13
    +  exclude:
    
    14
    +    - dummy

  • tests/integration/project/elements/compose-symlinks/foo-dir.bst
    1
    +kind: script
    
    2
    +
    
    3
    +depends:
    
    4
    +- filename: base.bst
    
    5
    +  type: build
    
    6
    +
    
    7
    +config:
    
    8
    +  commands:
    
    9
    +  - |
    
    10
    +    mkdir -p "%{install-root}/foo"
    
    11
    +    echo test >"%{install-root}/foo/foo.txt"

  • tests/integration/project/elements/compose-symlinks/integration-move-dir.bst
    1
    +kind: stack
    
    2
    +
    
    3
    +depends:
    
    4
    +- filename: base.bst
    
    5
    +
    
    6
    +public:
    
    7
    +  bst:
    
    8
    +    integration-commands:
    
    9
    +    - |
    
    10
    +      mkdir test
    
    11
    +      mv foo test/
    
    12
    +      ln -s /test/foo /foo



  • [Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]