Dear Maintainer,
It appears that ucf follows symbolic links before checking if those
symlinks correspond to diverted packages:
setq dest_file "$(readlink -q -m $temp_dest_file)" "The Destination file";
...
dest_file=$(dpkg-divert --truename "$dest_file")
This means that if a configuration file is diverted and a symlink is
installed in its place, ucf will try to act on the target of the symlink
instead of on the original config file.
Instead, a more reasonable behaviour would be the following:
1. First, resolve the real path of the directory that contains the
configuration file, but not the trailing symlink
2. Then, check if the resulting path is diverted
3. Finally, dereference the trailing symlink
Hristo, Thanks for this. I have been giving it some thought, but it is a thorny issue and I have not found a good solution (yet?). The root of the issue is alluded to in Debian Policy[1]: sharing and diverting configuration files is at best discouraged and likely to be broken. On that basis I am minded to close this as wontfix. Does that seem reasonable? Mark [1] https://www.debian.org/doc/debian-policy/ch-files.html#sharing-configuration-files
Perhaps it is. What I'm looking for is a way to manage configuration files. For me practically all configuration files (there are few exceptions, most notably `/etc/passwd`) fall into one of two categories: - The configuration file is provided by the package in one way or another, and its contents are always exactly what is provided by the package without any modification. - The configuration file is provided by the user. Any package management operations must not modify the configuration file. Ideally it would be possible keep a list of the configuration files that fall into the second category and apply it automatically. This would restore the original contents of all files removed from the list, and ensure that newly-added files will no longer be modified by package updates. Using `dpkg-divert --rename` + `dpkg --force-confnew,confmiss,confask` seems to work pretty well for dpkg-managed conffiles. The list of diversions is maintained to be exactly the list of user-managed configuration files. For ucf-managed configuration files, however, things are a bit more difficult. In my case all of them happen to fall into the second category, so currently my `/etc/ucf.conf` is `exit 0`. This works for now, but it is not ideal, and will become worse if more packages start using ucf.
Hristo, I have just implemented support for DPKG_FORCE in ucf[1] and that should be uploaded shortly. Maybe that will serve your needs? Mark [1] https://bugs.debian.org/925375
Yes, as long as ucf respects `dpkg-divert` the same way dpkg does.
Hi,
I got into the same issue while using config-package-dev
(https://debathena.mit.edu/config-packages/).
I have a configuration package that divert `sshd_config`.
But when upgrading openssh-server, ucf prompt the user as it detects
changes in the symlinked config file.
This is the same issue, but I'm using apt without force-new or anything.
I've followed the patch on #477773 from debathena page.
It seems that the added dpkg-divert check was already after the readlink
at that time, so I'm wondering if the implementation ever worked.
I tried to just implement what Hristo proposed and didn't find it too
much hacky:
Put the dpkg-divert check in a function "follow_divert"
Call that function in "handle_file_args" function:
```
follow_divert() {
dest_file="$1"
opt_package="$2"
# Follow dpkg-divert as though we are installed as part of $opt_package
divert_line=$(dpkg-divert --listpackage "$dest_file")
if [ -n "$divert_line" ]; then
# name of the package or 'LOCAL' for a local diversion
divert_package="$divert_line"
if [ "$divert_package" != "$opt_package" ]; then
dest_file=$(dpkg-divert --truename "$dest_file")
fi
fi
echo "$dest_file"
}
[...]
handle_file_args() {
[...]
temp_new_file="$1"
temp_dest_file=$(follow_divert "$2" "$opt_package")
[...]
}
```
What do you think ?
Alexis, Thanks I see this is a usage that would be good to support. I am testing your patch. Thanks. Could you provide a testsuite case as well? Mark
Hi, On 23/02/2025 17:39, Mark Hindley wrote: [...] I found that the general case is more complex, compared to what openssh-server does with ucf. openssh-server includes a md5sum history containing all hashes of previous sshd_config files. This makes my simple patch work. But without that md5sum history, it doesn't because the real destination file after dpkg-divert is not the same as before. This is the test I have locally so far: Before dpkg-divert: - ucf uses the file given in argument, /tmp/input.conf in the test - ucf hash the file and put something like "514654654968198179817 /tmp/input.conf" in its /var/lib/ucf/hashfile. config-package-dev's script is executed (dpkg-divert + symlinks): - dpkg-divert renames /tmp/input.conf into /tmp/input.conf.diverter-package-orig - A symlink is created at /tmp/input.conf pointing to /tmp/input.conf.diverter-package (which is provided by the config package using the config-package-dev script in its postinst) So we have at this point: - /tmp/input.conf -> input.conf.diverter-package - /tmp/input.conf.diverter-package-orig - /tmp/input.conf.diverter-package input.conf.diverter-package-orig contains the original input.conf data. input.conf.diverter-package contains the custom modified input.conf. Then ucf is called again to simulate a new input.conf version: - ucf check the destination file /tmp/input.conf for diversion (implemented by the patch). - ucf uses the diverted path "/tmp/input.conf.diverter-package-orig" instead. - ucf check if the file was modified by checking the md5sum and search in "/var/lib/ucf/hashfile" the path "/tmp/input.conf.diverter-package-orig". - ucf doesn't find it, then it check historical md5sums (which is what provides openssh-server package, but not my test). - ucf doesn't have an historical md5sums directory, so it asks the user. When I add --sum-file with a file containing the md5sum of the original input.conf and input2.conf, ucf won't ask the user. To handle the case without "--sum-file", I'm thinking about splitting the notion of "destination file" and "real destination file", the former would be /tmp/input.conf and the later /tmp/input.conf.diverter-package-orig. But I'm not sure this is worth the risk of regressions. In my case, I only wanted it to work with openssh-server, maybe that special case make it still worth to implement, but I wonder if there are that much packages using historical md5sums.