• Re: [gentoo-dev] PMS 13.2 / 13.4 replacing symlinks with directories an

    From Eli Schwartz@21:1/5 to All on Tue Jun 17 06:30:01 2025
    This is an OpenPGP/MIME signed message (RFC 4880 and 3156) --------------Z5KrFCFCM2ttPrKT2ZiYJCvh
    Content-Type: text/plain; charset=UTF-8
    Content-Transfer-Encoding: quoted-printable

    On 6/16/25 6:30 PM, Chí-Thanh Christopher Nguyễn wrote:
    Dear all,

    This is the continuation of a discussion in bug 957712[1], where it was suggested that portage might in the future allow to replace directories
    with symlinks. If you have additional insights or corrections please share.

    PMS 13.2 and 13.4[2] forbid replacing directories with symlinks and
    restrict doing the reverse.

    My understanding is that replacing directories with symlinks is a major
    no-no for package managers. dpkg[3] and rpm[4] also don't do this, and
    if package maintainers want to achieve this result, they have to use maintenance helper scripts.

    The rationale usually goes like this: Assume package A installs
    /foo/bar.txt
    and package B installs
    /foobar/baz.txt
    /foo->/foobar

    Then the resulting directory structure would depend on the merge order
    of packages, and if package B for example changes its symlink, then
    package A might lose access to its file.



    I don't think this is a fair or reasonable assessment.

    Your rpm link simply says "it is not possible". It then links to a bug
    report where people discuss the fact that its lack is an "urgent" issue
    and affected packages cause rpm to be unable to update anything. The rpm developer acknowledges that it's a conceptual flaw in rpm, but "It's not
    easy problem to solve in RPM". They... do not say why, at all.

    The official guidance for rpm is to use a pkg_preinst to:

    - just delete symlinks without checking ANYTHING

    - unconditionally move directories to .bak (actually .rpmmoved but
    basically the same), don't delete them because pkg_preinst cannot
    track CONTENTS and thus doesn't know what can be removed, better
    safe than sorry and the user can do data recovery, it's up to the
    user to inspect the moved contents


    Meanwhile, Debian says much the same thing explicitly in the FAQ:

    "As dpkg does not currently track file metadata, it does not know if a
    symlink or directory was switched by a previous package or by the
    sysadmin. As part of the dpkg credo, preserving human configuration is
    of utmost importance, and this kind of change has always been considered
    as so."

    Notice that MASSIVE qualifier.

    "dpkg does not currently track file metadata"


    What????????????????????????????????


    They then proceed to say "use pkg_preinst". Here's their documentation
    on how to handle it:

    https://manpages.debian.org/unstable/dpkg/dpkg-maintscript-helper.1.en.html#SYMLINK_AND_DIRECTORY_SWITCHES


    Complete with reconfirmation of the part where they said "dpkg doesn't
    know if the root account modified the symlink to point elsewhere".


    "This may seem a simple change to the preinst script at first, however
    that will result in some problems in case of admin local customization
    of the symlink"


    If the symlink object has *changed* from the destination that the
    package creator expected it to be (i.e. Gentoo's CONTENTS record) as
    manually written in the pkg_preinst -- remember dpkg simply does not
    record file metadata so this is *manually* written -- it is safe to
    replace. If it has been changed by the root user, simply ignore the directory/symlink and trust the user.


    For a directory object, it checks whether all files currently there are
    owned by that package, and is therefore safe to upgrade or if any of
    them are config-protected / belong to other packages / created by the
    user and just leaves it as a directory. Again, silently. "Trust the user".


    ...

    ...


    This is all genuinely horrible.

    However, that's a dpkg / rpm problem. It's not some general rule, moreso
    since both consider it to be a "bug" in their package managers. As a counterpoint, this works flawlessly in pacman (the Arch Linux package
    manager).

    In pacman, file conflicts are handled by treating symlink objects like
    ordinary files. One package cannot install inside another package's
    symlink, symlinks are not followed.

    Likewise, but independently, switching between symlinks and directories
    is fine, to the same extent that switching between files and directories
    is -- first, check what files are queued for *removal*, then check if
    the directory would still exist after removals, and if removals *would*
    remove that directory, it is safe to proceed with the transaction (that
    removes the files and installs a symlink).


    There might be a limited set of situations where such a replacement
    could be safe, such as a package replacing its own directory with a
    symlink and no other packages owning anything there. But it is
    potentially a can of worms. So best keep it that way?


    No, it's a tremendously useful feature, and conceptually simple.

    - does the package already own all files in the directory (e.g. file
    produced by keepdir)?

    - Yes? Replace.

    - No? Throw file conflict.


    The merge order of packages does not matter.

    If the other package installed first, then "No? Throw file conflict." It
    was also a conflict today. And it's a conflict with pacman too.


    If the other package installed second, it works today, it works with
    this proposal, and it's a conflict with pacman, so we are more flexible
    and powerful than the only competition. :) But handling it properly as
    well, "simply" requires preserving a record of files which, when
    installed, followed a symlink. And update the locations of installed
    files when their symlink record changes. In fact, solving this would fix longstanding issues with switching split-usr/merged-usr profiles...



    I think this "limited set of situations" is also the only practical
    situation anyone cares about, so it makes a lot of sense to support 100%
    of cases.


    However, there is a problem. Currently, if portage removes a directory
    plus all its contents when upgrading to a new version of a cat/pkg, it
    happens in two stages:

    - merging new version
    - "Safely unmerging already-installed instance..."

    Until step 2, the previously existing directory still exists.


    It's not obvious that PMS requires this. It doesn't explicitly spell out
    how the previous version of a package is removed...

    But, I *think* this should be covered by "The method used to perform the
    merge is not specified, so long as the end result is correct."

    If so, that would mean, "Ebuilds must not attempt to merge a regular
    file on top of any existing file that is not either a regular file or a
    symlink to a regular file." is talking about "an existing file" owned by
    a different package.


    --
    Eli Schwartz

    --------------Z5KrFCFCM2ttPrKT2ZiYJCvh--

    -----BEGIN PGP SIGNATURE-----

    wnsEABYIACMWIQTnFNnmK0TPZHnXm3qEp9ErcA0vVwUCaFDtwQUDAAAAAAAKCRCEp9ErcA0vV5+H AP9GX6a2UOz5Wmgf1pUDHN+5UtgFqSBs6Ki5ZPDC222YAQEA9Umg/dBLYVpS0Aixm/88OlaOyC8J HC9DqAgNut9iHAE=
    =xpI1
    -----END PGP SIGNATURE-----

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)