<feed xmlns='http://www.w3.org/2005/Atom'>
<title>android/rsend/app/src/main/java/invalid, branch 0.1.2</title>
<subtitle>[no description]</subtitle>
<link rel='alternate' type='text/html' href='http://git.0xlena.dev/android/rsend/'/>
<entry>
<title>app: drop --mkpath for compatibility with old remote rsyncs</title>
<updated>2026-07-01T00:00:00+00:00</updated>
<author>
<name>Lena</name>
<email>lena@omega</email>
</author>
<published>2026-07-01T00:00:00+00:00</published>
<link rel='alternate' type='text/html' href='http://git.0xlena.dev/android/rsend/commit/?id=44ebf6db6cf2725e18f0e1129f4005fd456b03dc'/>
<id>44ebf6db6cf2725e18f0e1129f4005fd456b03dc</id>
<content type='text'>
rsync forwards --mkpath to the remote side when sending, so a remote
rsync older than 3.2.3 (notably stock macOS, whose openrsync is
"rsync 2.6.9 compatible") rejects every sync with "unrecognized
option '--mkpath'".

rsync creates the final component of the destination path on its own,
so flat remote paths keep working everywhere, including the documented
rrsync setup whose root is pre-created. Only a nested remote path with
missing parents now needs a one-time mkdir -p on the server; the log
shows rsync's error when it is missing.

Reported-by: jsvk
Link: https://codeberg.org/0xlena/rsend/pulls/1
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
rsync forwards --mkpath to the remote side when sending, so a remote
rsync older than 3.2.3 (notably stock macOS, whose openrsync is
"rsync 2.6.9 compatible") rejects every sync with "unrecognized
option '--mkpath'".

rsync creates the final component of the destination path on its own,
so flat remote paths keep working everywhere, including the documented
rrsync setup whose root is pre-created. Only a nested remote path with
missing parents now needs a one-time mkdir -p on the server; the log
shows rsync's error when it is missing.

Reported-by: jsvk
Link: https://codeberg.org/0xlena/rsend/pulls/1
</pre>
</div>
</content>
</entry>
<entry>
<title>app: anchor the picker start path at the storage root</title>
<updated>2026-07-01T00:00:00+00:00</updated>
<author>
<name>Lena</name>
<email>lena@omega</email>
</author>
<published>2026-07-01T00:00:00+00:00</published>
<link rel='alternate' type='text/html' href='http://git.0xlena.dev/android/rsend/commit/?id=2c867cf95341daed1509e3cc48fec9de72cfe2f2'/>
<id>2c867cf95341daed1509e3cc48fec9de72cfe2f2</id>
<content type='text'>
The containment check was a bare prefix match, so a sibling such as
/storage/emulated/0-evil passed for a root of /storage/emulated/0.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The containment check was a bare prefix match, so a sibling such as
/storage/emulated/0-evil passed for a root of /storage/emulated/0.
</pre>
</div>
</content>
</entry>
<entry>
<title>app: write config atomically</title>
<updated>2026-07-01T00:00:00+00:00</updated>
<author>
<name>Lena</name>
<email>lena@omega</email>
</author>
<published>2026-07-01T00:00:00+00:00</published>
<link rel='alternate' type='text/html' href='http://git.0xlena.dev/android/rsend/commit/?id=d804eb4399850fe828462b3a1832a4c9df1541f8'/>
<id>d804eb4399850fe828462b3a1832a4c9df1541f8</id>
<content type='text'>
A crash mid-write corrupted config.json, and every later load then
threw on parse, crash-looping the app until its data was cleared,
losing the key and pinned host. Write to a temp file and rename.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
A crash mid-write corrupted config.json, and every later load then
threw on parse, crash-looping the app until its data was cleared,
losing the key and pinned host. Write to a temp file and rename.
</pre>
</div>
</content>
</entry>
<entry>
<title>app: kill rsync when a sync is stopped</title>
<updated>2026-07-01T00:00:00+00:00</updated>
<author>
<name>Lena</name>
<email>lena@omega</email>
</author>
<published>2026-07-01T00:00:00+00:00</published>
<link rel='alternate' type='text/html' href='http://git.0xlena.dev/android/rsend/commit/?id=d2745c0cca84ea006fa44edb4d9bbebffd35d917'/>
<id>d2745c0cca84ea006fa44edb4d9bbebffd35d917</id>
<content type='text'>
A stopped worker (schedule replaced, constraints lost) left rsync
running detached until its own network timeout, including a window
where a WiFi-only sync kept pushing on another network. A watchdog
coroutine destroys the process on cancellation, which also closes its
pipes and unblocks the log reader; the worker rethrows cancellation
instead of logging it as a folder error.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
A stopped worker (schedule replaced, constraints lost) left rsync
running detached until its own network timeout, including a window
where a WiFi-only sync kept pushing on another network. A watchdog
coroutine destroys the process on cancellation, which also closes its
pipes and unblocks the log reader; the worker rethrows cancellation
instead of logging it as a folder error.
</pre>
</div>
</content>
</entry>
<entry>
<title>app: refuse folder mappings with empty paths</title>
<updated>2026-07-01T00:00:00+00:00</updated>
<author>
<name>Lena</name>
<email>lena@omega</email>
</author>
<published>2026-07-01T00:00:00+00:00</published>
<link rel='alternate' type='text/html' href='http://git.0xlena.dev/android/rsend/commit/?id=f3889d4fb5659c94f4ec957219bebada8d1a67fb'/>
<id>f3889d4fb5659c94f4ec957219bebada8d1a67fb</id>
<content type='text'>
The trailing-slash fix-up turns an empty local path into /, so a blank
folder row would rsync the entire filesystem; an empty remote path
pushes into the rrsync root. Reject both when saving a folder, skip and
log them at run time in case the config was edited by hand, and log why
a sync was skipped when the app is not configured yet.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The trailing-slash fix-up turns an empty local path into /, so a blank
folder row would rsync the entire filesystem; an empty remote path
pushes into the rrsync root. Reject both when saving a folder, skip and
log them at run time in case the config was edited by hand, and log why
a sync was skipped when the app is not configured yet.
</pre>
</div>
</content>
</entry>
<entry>
<title>keys: never write the plaintext private key to disk</title>
<updated>2026-07-01T00:00:00+00:00</updated>
<author>
<name>Lena</name>
<email>lena@omega</email>
</author>
<published>2026-07-01T00:00:00+00:00</published>
<link rel='alternate' type='text/html' href='http://git.0xlena.dev/android/rsend/commit/?id=1da5637997e7971cbde77dbf642ea734fbb2f4cc'/>
<id>1da5637997e7971cbde77dbf642ea734fbb2f4cc</id>
<content type='text'>
rsh -keygen printed the pubkey but wrote the key pair into a directory,
so generating a key briefly left the plaintext private key on flash,
contradicting the documented invariant that it only ever exists in
memory. -keygen now emits the private key PEM on stdout and nothing
else; the app encrypts it immediately and derives the public key via
-pubkey, reusing the validated import path. Keygen failures now surface
as an error dialog instead of crashing the app from a bare thread.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
rsh -keygen printed the pubkey but wrote the key pair into a directory,
so generating a key briefly left the plaintext private key on flash,
contradicting the documented invariant that it only ever exists in
memory. -keygen now emits the private key PEM on stdout and nothing
else; the app encrypts it immediately and derives the public key via
-pubkey, reusing the validated import path. Keygen failures now surface
as an error dialog instead of crashing the app from a bare thread.
</pre>
</div>
</content>
</entry>
<entry>
<title>app: add a folder picker for local paths</title>
<updated>2026-06-01T00:00:00+00:00</updated>
<author>
<name>Lena</name>
<email>lena@omega</email>
</author>
<published>2026-06-01T00:00:00+00:00</published>
<link rel='alternate' type='text/html' href='http://git.0xlena.dev/android/rsend/commit/?id=72e37d2dac501faa300ca895c56c53eea43ae4ae'/>
<id>72e37d2dac501faa300ca895c56c53eea43ae4ae</id>
<content type='text'>
Typing absolute paths is error-prone; let the user browse real
filesystem folders and pick one. Stays on real paths (no SAF) so
rsync keeps operating on POSIX paths.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Typing absolute paths is error-prone; let the user browse real
filesystem folders and pick one. Stays on real paths (no SAF) so
rsync keeps operating on POSIX paths.
</pre>
</div>
</content>
</entry>
<entry>
<title>rsend: push phone folders to a home SSH host over rsync</title>
<updated>2026-01-01T00:00:00+00:00</updated>
<author>
<name>Lena</name>
<email>lena@omega</email>
</author>
<published>2026-01-01T00:00:00+00:00</published>
<link rel='alternate' type='text/html' href='http://git.0xlena.dev/android/rsend/commit/?id=7e04941bccb2683f8a6e3ee38a99c50129234dd1'/>
<id>7e04941bccb2683f8a6e3ee38a99c50129234dd1</id>
<content type='text'>
A small Android app for one-way folder backup, a KISS alternative to
Syncthing. It bundles rsync (built from pinned source via the NDK) and
a pure-Go SSH transport, both shipped in the APK as lib*.so and run from
the native library directory.

rsend pins the host key, stores the ed25519 identity Keystore-encrypted,
pushes each folder additively or as a mirror, and runs on demand or on a
WiFi-only schedule. The build is self-contained and reproducible: make
setup provisions the toolchain, make builds rsync, rsh, and the APK.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
A small Android app for one-way folder backup, a KISS alternative to
Syncthing. It bundles rsync (built from pinned source via the NDK) and
a pure-Go SSH transport, both shipped in the APK as lib*.so and run from
the native library directory.

rsend pins the host key, stores the ed25519 identity Keystore-encrypted,
pushes each folder additively or as a mirror, and runs on demand or on a
WiFi-only schedule. The build is self-contained and reproducible: make
setup provisions the toolchain, make builds rsync, rsh, and the APK.
</pre>
</div>
</content>
</entry>
</feed>
