Handle long symbolic links in apex
In many file systems, long symbolic link are stored outside of the inode
just like regular files. aosp/3382227 made a wrong assumption that all
symlinks in APEXes are short so that they are inlined in inode (aka fast
symlinks).
This CL fixes it. deapexer, when faced with a symlink, tries to read the
symlink by doing `stat` first to read the embedded target. If that
fails, it falls back to use `cat` for reading the target.
Bug: 390558705
Test: cd build/make/tools/releasetools/testdata
unzip foo.apex
debugfs -W -R "symlink long_symlink loooooooooooooooooooooooooooooooooooooooooooooooooong" apex_payload.img
debugfs -R "stat long_symlink" apex_payload.img
<shows EXTENTS: ... , not Fast link dest>
zip -u foo.apex apex_payload.img
deapexer extract foo.apex flatten
readsymlink flatten/long_symlink
<shows looooooooooooooooooooooooooooo....oooong>
Change-Id: I8d20067f99350d4b8ecd2fe7cc5ff87a08379b76
diff --git a/tools/deapexer.py b/tools/deapexer.py
index ade5945..c42724c 100755
--- a/tools/deapexer.py
+++ b/tools/deapexer.py
@@ -295,9 +295,16 @@
# Output of stat for a symlink should have the following line:
# Fast link dest: \"%.*s\"
m = re.search(r'\bFast link dest: \"(.+)\"\n', stdout)
- if not m:
+ if m:
+ return m.group(1)
+
+ # if above match fails, it means it's a slow link. Use cat.
+ output = subprocess.check_output([self._debugfs, '-R', f'cat {entry.full_path}',
+ self._payload], text=True, stderr=subprocess.DEVNULL)
+
+ if not output:
sys.exit('failed to read symlink target')
- return m.group(1)
+ return output
def write_entry(self, entry, out_dir):
dest = os.path.normpath(os.path.join(out_dir, entry.full_path))