Recent

Author Topic: Reading and absolutising a symlink  (Read 769 times)

MarkMLl

  • Hero Member
  • *****
  • Posts: 5862
Reading and absolutising a symlink
« on: October 24, 2022, 09:21:21 am »
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
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

PascalDragon

  • Hero Member
  • *****
  • Posts: 4872
  • Compiler Developer
Re: Reading and absolutising a symlink
« Reply #1 on: October 25, 2022, 09:01:30 pm »
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

  • Hero Member
  • *****
  • Posts: 5862
Re: Reading and absolutising a symlink
« Reply #2 on: October 25, 2022, 09:13:59 pm »
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
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

PascalDragon

  • Hero Member
  • *****
  • Posts: 4872
  • Compiler Developer
Re: Reading and absolutising a symlink
« Reply #3 on: October 26, 2022, 07:38:57 am »
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.

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.
« Last Edit: October 26, 2022, 07:41:04 am by PascalDragon »

MarkMLl

  • Hero Member
  • *****
  • Posts: 5862
Re: Reading and absolutising a symlink
« Reply #4 on: October 26, 2022, 09:14:53 am »
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.

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
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Kays

  • Sr. Member
  • ****
  • Posts: 478
  • Whasup!?
    • KaiBurghardt.de
Re: Reading and absolutising a symlink
« Reply #5 on: October 26, 2022, 12:18:27 pm »
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 […] to
Code: [Select]
/etc/resolv.conf -> ../run/resolvconf/resolv.conf
The 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?
Yours Sincerely
Kai Burghardt

MarkMLl

  • Hero Member
  • *****
  • Posts: 5862
Re: Reading and absolutising a symlink
« Reply #6 on: October 26, 2022, 12:27:38 pm »
The 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
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

PascalDragon

  • Hero Member
  • *****
  • Posts: 4872
  • Compiler Developer
Re: Reading and absolutising a symlink
« Reply #7 on: October 27, 2022, 07:37:37 am »
The 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

  • Hero Member
  • *****
  • Posts: 2283
    • tomboy-ng, a rewrite of the classic Tomboy
Re: Reading and absolutising a symlink
« Reply #8 on: October 27, 2022, 08:03:21 am »
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][+][-]
  1. dbannon@dell:~$ mkdir -p BLAR/run
  2. dbannon@dell:~$ mkdir BLAR/etc
  3. dbannon@dell:~$ cd BLAR/
  4. dbannon@dell:~/BLAR$ echo "blar" > run/blar.txt
  5. dbannon@dell:~/BLAR$ cd etc
  6. dbannon@dell:~/BLAR/etc$ ln -s ../run/blar.txt
  7. dbannon@dell:~/BLAR/etc$ ls -l
  8. total 0
  9. lrwxrwxrwx 1 dbannon dbannon 15 Oct 27 16:48 blar.txt -> ../run/blar.txt
  10.  
  11. dbannon@dell:~/BLAR/etc$ cat ./blar.txt
  12. blar
  13. dbannon@dell:~/BLAR$ cd
  14. dbannon@dell:~$ cat BLAR/etc/blar.txt
  15. blar
  16. dbannon@dell:~$ cd /
  17. dbannon@dell:/$ cat /home/dbannon/BLAR/etc/blar.txt
  18. blar

Davo
Lazarus 2, Linux (and reluctantly Win10, OSX)
My Project - https://github.com/tomboy-notes/tomboy-ng

MarkMLl

  • Hero Member
  • *****
  • Posts: 5862
Re: Reading and absolutising a symlink
« Reply #9 on: October 27, 2022, 08:42:33 am »
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.

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
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

MarkMLl

  • Hero Member
  • *****
  • Posts: 5862
Re: Reading and absolutising a symlink
« Reply #10 on: October 27, 2022, 08:55:24 am »
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.

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
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

 

TinyPortal © 2005-2018