Sample Header Ad - 728x90

tar compress inside android adb su root -c sub command produces empty tar file

3 votes
1 answer
121 views
I just stumbled upon a weird behavior on android: echo test>/data/local/tmp/test.txt su root -c "cat /data/local/tmp/test.txt && \ tar -cvzf /data/local/tmp/test.tar.gz /data/local/tmp/test.txt && \ echo $?" ls -alh /data/local/tmp/test.txt This will produce an empty test.tar.gz: test removing leading '/' from member names data/local/tmp/test.txt 0 -rw-r--r-- 1 root root 0 2025-01-09 17:43 /data/local/tmp/test.tar.gz Running without su root -c I will get a 120 byte tar.gz: -rw-r--r-- 1 root root 120 2025-01-09 17:47 /data/local/tmp/test.tar.gz Adding a sleep like this: su root -c "tar -cvzf /data/local/tmp/test.tar.gz /data/local/tmp/test.txt && sleep 1" Also produces a 120 byte tar.gz. *Update:* Doing this with a 50mb file, the tar subcommand blocks until it's finished and produces an invalid tar.gz which is short of 22031 bytes to a valid tar.gz produced without su -c $ ls -alh /system/apex/com.android.art.release.apex -rw-r--r-- 1 root root 54M 2009-01-01 00:00 /system/apex/com.android.art.release.apex $ tar -cvzf /data/local/tmp/big.tar.gz /system/apex/com.android.art.release.apex $ su root -c "tar -cvzf /data/local/tmp/bigsu.tar.gz /system/apex/com.android.art.release.apex" removing leading '/' from member names system/apex/com.android.art.release.apex $ ls -al /data/local/tmp/b* -rw-r--r-- 1 root root 22541839 2025-01-09 21:43 /data/local/tmp/big.tar.gz -rw-r--r-- 1 root root 22519808 2025-01-09 21:33 /data/local/tmp/bigsu.tar.gz $ tar -xvzf /data/local/tmp/bigsu.tar.gz /data/local/tmp/big.apex ; echo $? zcat: gzclose: Inappropriate ioctl for device tar: EOF: Illegal seek 1 $ tar -xvzf /data/local/tmp/big.tar.gz /data/local/tmp/big.apex ; echo $? 0 Same behavior when using another user besides root. This problem occurs on an android 11 emulator. I wasn't able to reproduce this on my linux servers. The only way I can explain it is that the write buffer from tar is not flushed to the emulated disk. A stat to the file inside the subcommand makes it flush the data correctly: $ su root -c "tar -cvzf /data/local/tmp/test.tar.gz /data/local/tmp/test.txt && stat /data/local/tmp/test.tar.gz" removing leading '/' from member names data/local/tmp/test.txt File: /data/local/tmp/test.tar.gz Size: 120 Blocks: 16 IO Blocks: 512 regular file Device: fd05h/64773d Inode: 65546 Links: 1 Device type: 0,0 Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2025-01-09 17:43:44.964000000 +0000 Modify: 2025-01-09 22:00:28.496000000 +0000 Change: 2025-01-09 22:00:28.496000000 +0000 $ ls -alh /data/local/tmp/test.tar.gz -rw-r--r-- 1 root root 120 2025-01-09 22:00 /data/local/tmp/test.tar.gz But why on earth would ending the subshell prevent flushing of the output file? When tar exits with a success exit 0, that means the written data should already be handled and flushed by the kernel. Simple copying does not have the flush problem. So it might be a tar bug. su root -c "cp /system/apex/com.android.art.release.apex>/data/local/tmp/release.apex" su root -c "cat /system/apex/com.android.art.release.apex>/data/local/tmp/releasecat.apex" ls -al /data/local/tmp/release* -rw-r--r-- 1 root root 56510850 2025-01-09 22:31 /data/local/tmp/release.apex -rw-r--r-- 1 root root 56510850 2025-01-09 22:33 /data/local/tmp/releasecat.apex The tar version of busybox does not have this problem! $ su root -c "/data/adb/magisk/busybox tar --version" tar (busybox) 1.36.1-Magisk $ su root -c "/data/adb/magisk/busybox tar -cvzf /data/local/tmp/test.tar.gz /data/local/tmp/test.txt" $ ls -alh /data/local/tmp/test.tar.gz -rw-r--r-- 1 root root 120 2025-01-09 22:42 /data/local/tmp/test.tar.gz *Notes:* - tar version toybox 0.8.3-android - same when using /sdcard/Download as a directory.
Asked by 5andr0 (113 rep)
Jan 9, 2025, 05:59 PM
Last activity: Jan 10, 2025, 01:52 PM