Reading and absolutising a symlink lazarus / 32-Linux ---------------------------------------------------------------------- MarkMLl · 2022-10-24 07:21 Is there a concise way of reading a symlink and making sure that the result represents an absolute file location? As a specific example, Debian is switching from Code: [Select]/mnt/etc/resolv.conf -> /etc/resolvconf/run/resolv.conf to Code: [Select]/etc/resolv.conf -> ../run/resolvconf/resolv.conf fpReadLink() expands that relative symlink verbatim, while what's needed is its expansion relative to its original (absolute) location. MarkMLl ---------------------------------------------------------------------- PascalDragon · 2022-10-25 19:01 You can simply pass the link returned by fpReadLink to ExpandFileName with the directory the link resides in passed as second parameter. However this requires FPC 3.3.1. ---------------------------------------------------------------------- MarkMLl · 2022-10-25 19:13 Thanks. I notice that the documentation at https://www.freepascal.org/docs- html/current/rtl/sysutils/expandfilename.html (which is supposedly for the current version) refers to a BasePath parameter, which is neither described forward nor (as far as I can find) in the current version's RTL sources... presumably that ties in with your 3.3.1 comment. MarkMLl ---------------------------------------------------------------------- PascalDragon · 2022-10-26 05:38 Quote from: MarkMLl on October 25, 2022, 09:13:59 pmThanks. I notice that the documentation at https://www.freepascal.org/docs- html/current/rtl/sysutils/expandfilename.html (which is supposedly for the current version) refers to a BasePath parameter, which is neither described forward nor (as far as I can find) in the current version's RTL sources... presumably that ties in with your 3.3.1 comment. The documentation is for 3.2.2, but it seems that somebody updated the documentation when 3.2.2 was prepared for release without checking against the real declarations (those listed at the top are the correct ones for 3.2.2), cause the changes for ExpandFileName hadn't been merged back to 3.2.x... Edit: The daily documentation which is generated for the development version has the correct combination. ---------------------------------------------------------------------- MarkMLl · 2022-10-26 07:14 Quote from: PascalDragon on October 26, 2022, 07:38:57 amThe documentation is for 3.2.2, but it seems that somebody updated the documentation when 3.2.2 was prepared for release without checking against the real declarations (those listed at the top are the correct ones for 3.2.2), cause the changes for ExpandFileName hadn't been merged back to 3.2.x... Edit: The daily documentation which is generated for the development version has the correct combination. Thanks for that, I'll hack the link into my TODO in the problematic bit of source. I practice I want to keep compatibility with (I think) 3.0.4 since one of my test systems is an x86 laptop which due to the usual convoluted chain of hardware, driver modules etc. can't be brought fully up to date. MarkMLl ---------------------------------------------------------------------- Kays · 2022-10-26 10:18 Quote from: MarkMLl on October 24, 2022, 09:21:21 amIs there a concise way of reading a symlink and making sure that the result represents an absolute file location? As a specific example, Debian is switching […] toCode: [Select]/etc/resolv.conf -> ../run/resolvconf/resolv.confThe full path /etc/../run/resolvconf/resolv.conf is already absolute. It starts with a forward slash. Simple concatenation of the symlink’s location and its target (unless the target is specifying an absolute path, obviously). If I understand you correctly, your task is to collapse unnecessary directory traversal. So /../../../../../../.. is collapsed to to /. The problem is, path_resolution(7) depends on many factors. It’s not done with a plain string pattern replacement. PS: What would be your expected result if, say, the directory resolvconf was itself a symbolic link again? ---------------------------------------------------------------------- MarkMLl · 2022-10-26 10:27 Quote from: Kays on October 26, 2022, 12:18:27 pmThe full path /etc/../run/resolvconf/resolv.conf is already absolute. It starts with a forward slash. Simple concatenation of the symlink’s location and its target (unless the target is specifying an absolute path, obviously). If I understand you correctly, your task is to collapse unnecessary directory traversal. So /../../../../../../.. is collapsed to to /. The problem is, path_resolution(7) depends on many factors. It’s not done with a plain string pattern replacement. PS: What would be your expected result if, say, the directory resolvconf was itself a symbolic link again? It DOES NOT START with a slash!!!!!! What part of the ls output do you not understand? Code: [Select]$ ls -l /etc/resolv.conf lrwxrwxrwx 1 root root 29 Oct 22 18:41 /etc/resolv.conf -> ../run/resolvconf/resolv.conf They've changed it so a symlink that USED TO START with a slash NO LONGER DOES SO!!!!! The result of that is that a program running in any directory which is not one level up from / (i.e. as shown in $PWD) misinterprets that relative path unless it dereferences the symlink with explicit reference to the basename (hence @PascalDragon's comment about the slightly changed RTL routine). MarkMLl ---------------------------------------------------------------------- PascalDragon · 2022-10-27 05:37 Quote from: MarkMLl on October 26, 2022, 12:27:38 pmQuote from: Kays on October 26, 2022, 12:18:27 pmThe full path /etc/../run/resolvconf/resolv.conf is already absolute. It starts with a forward slash. Simple concatenation of the symlink’s location and its target (unless the target is specifying an absolute path, obviously). If I understand you correctly, your task is to collapse unnecessary directory traversal. So /../../../../../../.. is collapsed to to /. The problem is, path_resolution(7) depends on many factors. It’s not done with a plain string pattern replacement. PS: What would be your expected result if, say, the directory resolvconf was itself a symbolic link again? It DOES NOT START with a slash!!!!!! What part of the ls output do you not understand? What Kays means is that the destination of a symbolic link is - if it's relative - determined by the location of the symbolic link (in this case /etc) and the target (in this case ../run/resolvconf/resolv.conf). So if you access /etc/resolv.conf the kernel will always access /etc/../run/resolvconf/resolv.conf which is an absolute path. So no matter from where you access the symlink the kernel will do this correctly. Just do a cat /etc/resolv.conf once from /etc and once from / and you'll get the same output. ---------------------------------------------------------------------- dbannon · 2022-10-27 06:03 While the symlink itself is relative, its relative to itself. Clearly it would be broken if moved but thats not going to happen. Where you use the symlink from means nothing. Code: Bash  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i dbannon@dell:~$ mkdir -p BLAR/rundbannon@dell:~$ mkdir BLAR/etcdbannon@dell:~$ cd BLAR/dbannon@dell:~/BLAR$ echo "blar" > run/blar.txtdbannon@dell:~/BLAR$ cd etcdbannon@dell:~/BLAR/etc$ ln -s ../run/blar.txt dbannon@dell:~/BLAR/etc$ ls -ltotal 0lrwxrwxrwx 1 dbannon dbannon 15 Oct 27 16:48 blar.txt -> ../run/blar.txt dbannon@dell:~/BLAR/etc$ cat ./blar.txt blardbannon@dell:~/BLAR$ cd dbannon@dell:~$ cat BLAR/etc/blar.txtblardbannon@dell:~$ cd /dbannon@dell:/$ cat /home/dbannon/BLAR/etc/blar.txt blar Davo ---------------------------------------------------------------------- MarkMLl · 2022-10-27 06:42 Quote from: PascalDragon on October 27, 2022, 07:37:37 amWhat Kays means is that the destination of a symbolic link is - if it's relative - determined by the location of the symbolic link (in this case /etc) and the target (in this case ../run/resolvconf/resolv.conf). So if you access /etc/resolv.conf the kernel will always access /etc/../run/resolvconf/resolv.conf which is an absolute path. So no matter from where you access the symlink the kernel will do this correctly. Just do a cat /etc/resolv.conf once from /etc and once from / and you'll get the same output. True. But while I forget the detail there was some reason in this case why I did have to resolve the actual name... it might have been something to do with the way that Debian (by default) does an auto- update of that file with the content likely to vary wildly (e.g. flip between a local server presented by DHCP, to a remote one presented by a router). MarkMLl ---------------------------------------------------------------------- MarkMLl · 2022-10-27 06:55 Quote from: dbannon on October 27, 2022, 08:03:21 amWhile the symlink itself is relative, its relative to itself. Clearly it would be broken if moved but thats not going to happen. Where you use the symlink from means nothing. It doesn't move, but it does get updated (which is why Debian has it in /run). Looking at the code and then Googling to see if the TStringList.LoadFromFile() had any peculiarities related to symlinks, I get to https://forum.lazarus.freepascal.org/index.php?topic=51191.0 which explains what went on. Basically, a repeated access of that file was failing after a few hours so I needed to drill down to find out what was going wrong, the problem turned out to be a UDP socket not getting closed so while it looks as though I could now revert to ignoring the fact that the file is accessed via a symlink it adds useful error reporting. MarkMLl