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)