The previous implementation had two correctness issues:
1. flock on .tmp was ineffective for cross-process exclusion.
After fs::rename(), the .tmp inode disappears. A second process
opening .tmp gets a brand-new inode, so both processes hold flocks
on different inodes simultaneously — no mutual exclusion occurs.
2. The critical section was too narrow. The in-process tokio::Mutex
only serializes tasks within the same process. Two separate mdrs
processes could both read the cache, both decide a refresh was
needed, and both call the token-refresh endpoint before either had
written the new token back — risking double-refresh and potential
failures on servers that use refresh-token rotation.
Fix: introduce a dedicated `cache/{remote}.lock` file as the cross-
process advisory lock target. The lock file is never renamed, so its
inode remains stable for the entire critical section. The flock now
wraps the complete read-check-refresh-write cycle in
load_cache_with_token_refresh(), and the redundant flock on .tmp in
refresh_and_persist() is removed.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
mdrs
mdrs is a command-line client for uploading and downloading files to and from an MDRS-based repository.
Installing
Build from source
cargo build --release
The compiled binary will be available at target/release/mdrs.
To build a fully static binary for Linux:
cargo build --release --target x86_64-unknown-linux-musl
Configuration
Environment variables
The following environment variables can be set, either in the shell or via a .env file placed in the working directory:
| Variable | Default | Description |
|---|---|---|
MDRS_CLIENT_CONFIG_DIRNAME |
~/.mdrs-client |
Directory where config and login cache files are stored |
MDRS_CLIENT_CONCURRENT |
10 |
Number of concurrent file transfers for upload/download |
Example Usage
config create
Register a remote host.
mdrs config create neurodata https://neurodata.riken.jp/api
config update
Update the URL of a registered remote host.
mdrs config update neurodata https://neurodata.riken.jp/api
config list
List registered remote hosts.
mdrs config list
mdrs config ls
config delete
Remove a registered remote host.
mdrs config delete neurodata
mdrs config rm neurodata
login
Log in to a remote host and cache credentials.
mdrs login neurodata:
Username: (enter your login name)
Password: (enter your password)
mdrs login -u USERNAME -p PASSWORD neurodata:
logout
Log out from a remote host and remove cached credentials.
mdrs logout neurodata:
whoami
Print the currently logged-in user name.
mdrs whoami neurodata:
labs
List all laboratories accessible to the current user.
mdrs labs neurodata:
ls
List the contents of a remote folder.
mdrs ls neurodata:/NIU/Repository/
mdrs ls -p SHARING_PASSWORD neurodata:/NIU/Repository/PW_Open/
mdrs ls -r neurodata:/NIU/Repository/Dataset1/
mdrs ls -J -r neurodata:/NIU/Repository/Dataset1/
mdrs ls -q neurodata:/NIU/Repository/
mkdir
Create a new remote folder.
mdrs mkdir neurodata:/NIU/Repository/TEST
upload
Upload a file or directory to a remote folder.
mdrs upload ./sample.dat neurodata:/NIU/Repository/TEST/
mdrs upload -r ./dataset neurodata:/NIU/Repository/TEST/
mdrs upload -r --skip-if-exists ./dataset neurodata:/NIU/Repository/TEST/
download
Download a file or folder from a remote path.
mdrs download neurodata:/NIU/Repository/TEST/sample.dat ./
mdrs download -r neurodata:/NIU/Repository/TEST/dataset/ ./
mdrs download -p SHARING_PASSWORD neurodata:/NIU/Repository/PW_Open/Readme.dat ./
mdrs download -r --exclude /NIU/Repository/TEST/dataset/skip neurodata:/NIU/Repository/TEST/dataset/ ./
mdrs download -r --skip-if-exists neurodata:/NIU/Repository/TEST/dataset/ ./
mv
Move or rename a file or folder on the remote.
mdrs mv neurodata:/NIU/Repository/TEST/sample.dat neurodata:/NIU/Repository/TEST2/sample2.dat
mdrs mv neurodata:/NIU/Repository/TEST/dataset neurodata:/NIU/Repository/TEST2/
cp
Copy a file or folder on the remote.
mdrs cp neurodata:/NIU/Repository/TEST/sample.dat neurodata:/NIU/Repository/TEST2/sample2.dat
mdrs cp -r neurodata:/NIU/Repository/TEST/dataset neurodata:/NIU/Repository/TEST2/
rm
Remove a file or folder from the remote.
mdrs rm neurodata:/NIU/Repository/TEST/sample.dat
mdrs rm -r neurodata:/NIU/Repository/TEST/dataset
chacl
Change the access level of a remote folder.
mdrs chacl private neurodata:/NIU/Repository/Private
mdrs chacl cbs_open -r neurodata:/NIU/Repository/CBS_Open
mdrs chacl pw_open -r -p SHARING_PASSWORD neurodata:/NIU/Repository/PW_Open
Available access levels: private, public, pw_open, cbs_open, 5kikan_open, cbs_pw_open, 5kikan_pw_open
metadata
Show metadata for a remote folder.
mdrs metadata neurodata:/NIU/Repository/TEST/
mdrs metadata -p SHARING_PASSWORD neurodata:/NIU/Repository/PW_Open/
file-metadata
Show metadata for a remote file.
mdrs file-metadata neurodata:/NIU/Repository/TEST/dataset/sample.dat
mdrs file-metadata -p SHARING_PASSWORD neurodata:/NIU/Repository/PW_Open/Readme.txt
version
Show the tool name and version number.
mdrs version
help
Show help for a command.
mdrs --help
mdrs upload --help
License
MIT © 2026- Neuroinformatics Unit, RIKEN CBS