Android Question rsync and sdcard writing on API23

warwound

Expert
Licensed User
Longtime User
We are running rsync in daemon mode on our android tablets in order to sync many GBs of media files between the tablets and our server.
We have tablets running android api19 and tablets running android api23.
The process works perfectly on api19 but fails on api23.

We are using a USB connection to sync the tablets (not wifi), with TCP being port forwarded by adb.
On api19 adb can only forward a port from a computer to an android device, it can't forward a port from an android device to a computer and that's why the tablets are running rsync in daemon mode instead of client mode.
(The connection must be initiated on the computer not the tablet).

Anway our problem is caused by the changes to sdcard writing permissions in api23.
rsync fails with various errors but a typical error is:

rsync: read error: Connection reset by peer (104)
rsync error: error in socket IO (code 10) at io.c(785) [sender=3.1.2]

We then often see a lot of 0 byte files on the tablet, android has started to write a new file to sdcard but failed.

Our rsyncd.conf file reads:

address = 127.0.0.1
gid = sdcard_rw
list = yes
lock file = <PATH_RSYNC_INTERNAL>/rsyncd.lock
log file = <PATH_RSYNC_INTERNAL>/rsyncd.log
max connections = 6
pid file = <PATH_RSYNC_INTERNAL>/rsyncd.pid
read only = no
# strict modes = false
timeout = 300
uid = root

[sdcard]
comment = sdcard
path = <PATH_SDCARD>

I've tried setting gid to root as well as sdcard_rw but the sync still fails.
Our b4a app - the app that starts the rsync daemon - starts the daemon as root and has the WRTIE_EXTERNAL_STORAGE permission.
Our rsync android binary is also compatible with api23's new Position Independant Executable policy.

I've spent hours trawling through search results looking for a solution but nothing so far has worked.

Has anyone managed to run rsync on an android api23 device and successfully written to the device's external storage?
Can anyone suggest where the problem is?

Thanks.
 

warwound

Expert
Licensed User
Longtime User
Try to sync the files under RuntimePermissions.GetSafeDirDefaultExternal("")

It didn't work!

My Manifest Editor is:

AddManifestText(
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="23"/>
<supports-screens android:largeScreens="true"
android:normalScreens="true"
android:smallScreens="true"
android:anyDensity="true"/>)
SetApplicationAttribute(android:icon, "@drawable/icon")
SetApplicationAttribute(android:label, "$LABEL$")
'End of default text.

AddPermission(android.permission.WAKE_LOCK)
SetActivityAttribute(Main, android:theme, "@android:style/Theme.NoTitleBar.Fullscreen")

And here's the (compiled) manifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="my.package.name"
android:versionCode="23"
android:versionName="2.00_pie"
android:installLocation="internalOnly">

<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="23"/>
<supports-screens android:largeScreens="true"
android:normalScreens="true"
android:smallScreens="true"
android:anyDensity="true"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>
<uses-permission android:name="android.permission.REBOOT"/>
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.UPDATE_DEVICE_STATS"/>
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE"/>
<uses-permission android:name="android.permission.GET_TASKS"/>
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<application
android:icon="@drawable/icon"
android:label="My App">
<activity
android:windowSoftInputMode="stateHidden"
android:launchMode="singleTop"
android:name=".main"
android:label="My App"
android:screenOrientation="portrait"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

</activity>
<service android:name=".autostart">
</service>
<receiver android:name=".autostart$autostart_BR">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
<activity
android:windowSoftInputMode="stateHidden"
android:launchMode="singleTop"
android:name=".powerdown"
android:label="My App"
android:screenOrientation="portrait">
</activity>
<activity
android:windowSoftInputMode="stateHidden"
android:launchMode="singleTop"
android:name=".screen"
android:label="My App"
android:screenOrientation="portrait">
</activity>
<activity
android:windowSoftInputMode="stateHidden"
android:launchMode="singleTop"
android:name=".flash"
android:label="My App"
android:screenOrientation="portrait">
</activity>
<service android:name="anywheresoftware.b4a.samples.httputils2.httputils2service">
</service>
<receiver android:name="anywheresoftware.b4a.samples.httputils2.httputils2service$httputils2service_BR">
</receiver>
</application>
</manifest>

Does that show anything that's relevant?
I used api23 android.jar to compile.
 
Upvote 0

warwound

Expert
Licensed User
Longtime User
I guess that rsync doesn't use your app permissions at all.

Yep it seems that way - and makes sense that android permissions only apply to an android application and not to a shell process.

But if that is the case we are still confused as to why our rsync daemon running as root cannot write to the external storage.
I recall that api 23 used a newer version of SE Linux as it's base and i suspect this newer version of SE Linux is preventing our rsync from behaving the same on api 23 as it does on api 19.
 
Upvote 0

warwound

Expert
Licensed User
Longtime User
I have a solution....

On api23 devices i am running rsync with it's --dry-run option.
I parse the output from the dry run and then use adb push, adb shell rm and adb shell rmdir to make the modifications to the android filesystem!
 
Upvote 0
Top