15 Commits
v0.2.3 ... main

Author SHA1 Message Date
Ryo Nakamura
1313853d7d adjust mscp.rst for v0.2.4 2025-11-08 19:32:30 +09:00
Ryo Nakamura
e621035002 bump version to 0.2.4 2025-11-08 19:25:08 +09:00
Ryo Nakamura
ef8994d21e cache auth_bit_mask after the first none auth attempt
This fixes #36, password auth does not occur.
2025-11-08 18:50:44 +09:00
Ryo Nakamura
81d46a1cd1 test: add test_passwordauth_without_pubkey
It reproduces #36
2025-11-08 18:50:44 +09:00
Ryo Nakamura
07366397a8 test: use fixture to cleanup copying and copied files 2025-11-08 18:50:44 +09:00
Ryo Nakamura
f12d10a988 use size_t for bitrate (for portability) 2025-11-08 18:50:44 +09:00
Ryo Nakamura
afe2182456 gitignore: add .cache 2025-11-08 18:50:44 +09:00
Ryo Nakamura
c4d8e64fab remove unnecessary code lines 2025-11-08 18:50:44 +09:00
Ryo Nakamura
049600a39f adjust the timing of verbose printing of the bw limit value 2025-11-08 18:50:44 +09:00
Ryo Nakamura
fa15e9093d Merge pull request #39 from spikeyspik/main
Fix: fallback to default terminal size on no tty
2025-11-08 18:48:58 +09:00
Ryo Nakamura
5bca31b75d Merge pull request #38 from Oink70/main
Support compiling on Debian and Devuan
2025-11-08 16:48:43 +09:00
spikeyspik
f65cedb4de Fix: fallback to default terminal size on no tty 2025-10-24 21:31:12 +03:00
Oink70
8bad10e42b Add Devuan to script 2025-10-23 10:24:11 +00:00
Oink70
8de47933bf Add Debian to script 2025-10-23 10:02:49 +00:00
Ryo Nakamura
440f25b3a5 adjust mscp.rst for v0.2.3 2025-08-12 19:34:31 +09:00
15 changed files with 139 additions and 128 deletions

1
.gitignore vendored
View File

@@ -3,5 +3,6 @@ html
compile_commands.json
CMakeUserPresets.json
.*.swp
.cache
include/mscp_version.h

View File

@@ -1 +1 @@
0.2.3
0.2.4

10
debian/changelog vendored
View File

@@ -1,4 +1,12 @@
mscp (0.2.3) UNRELEASED; urgency=medium
mscp (0.2.4) UNRELEASED; urgency=medium
* fix password auth does not work (issue #36)
* add Debian and Devuan to the install dep script (pr #38)
* fallback to default terminal size on no tty (pr #39)
-- Ryo Nakamura <upa@haeena.net> Sat, 08 Nov 2025 19:23:07 +0900
mscp (0.2.3) unstable; urgency=medium
* bump libssh version to 0.11.2 (#25)
* adopt new AIO read API of libssh

View File

@@ -2,7 +2,7 @@
MSCP
====
:Date: v0.2.1
:Date: v0.2.4
NAME
====

View File

@@ -28,6 +28,7 @@
#include <stdbool.h>
#include <limits.h>
#include <stdlib.h>
#define MSCP_DIRECTION_L2R 1 /** Indicates local to remote copy */
#define MSCP_DIRECTION_R2L 2 /** Indicates remote to local copy */

View File

@@ -38,6 +38,9 @@ make -C build install DESTDIR=%{buildroot}
%changelog
* Sat Nov 08 2025 Ryo Nakamura <upa@haeena.net> - 0.2.4-1
- RPM release for v0.2.4
* Tue Aug 12 2025 Ryo Nakamura <upa@haeena.net> - 0.2.3-1
- RPM release for v0.2.3

View File

@@ -47,7 +47,7 @@ case $platform in
cmd="brew install"
pkgs="openssl@3"
;;
Linux-ubuntu*)
Linux-ubuntu* | Linux-debian* | Linux-devuan*)
cmd="apt-get install --no-install-recommends -y"
pkgs="gcc make cmake zlib1g-dev libssl-dev libkrb5-dev"
;;

View File

@@ -50,8 +50,6 @@ int bwlimit_init(struct bwlimit *bw, uint64_t bps, uint64_t win)
#define timespeccmp(a, b, expr) \
((a.tv_sec * 1000000000 + a.tv_nsec) expr(b.tv_sec * 1000000000 + b.tv_nsec))
#include <stdio.h>
int bwlimit_wait(struct bwlimit *bw, size_t nr_bytes)
{
struct timespec now, end, rq, rm;

View File

@@ -9,10 +9,10 @@
#include <semaphore.h>
struct bwlimit {
sem_t *sem; /* semaphore */
uint64_t bps; /* limit bit-rate (bps) */
uint64_t win; /* window size (msec) */
size_t amt; /* amount of bytes can be sent in a window */
sem_t *sem; /* semaphore */
size_t bps; /* limit bit-rate (bps) */
size_t win; /* window size (msec) */
size_t amt; /* amount of bytes can be sent in a window */
ssize_t credit; /* remaining bytes can be sent in a window */
struct timespec wstart, wend; /* window start time and end time */

View File

@@ -101,7 +101,6 @@ MDIR *mscp_opendir_wrapped(const char *path)
void mscp_closedir(MDIR *md)
{
int ret;
if (md->remote)
sftp_closedir(md->remote);
else

View File

@@ -117,8 +117,6 @@ char *split_user_host_path(const char *s, char **userp, char **hostp, char **pat
return NULL;
}
user = NULL;
host = NULL;
path = tmp;
for (cp = tmp; *cp; cp++) {
if (*cp == '@' && (cp > tmp) && *(cp - 1) != '\\' && user == NULL) {
@@ -211,7 +209,6 @@ struct target *validate_targets(char **arg, int len)
pr_err("calloc: %s", strerrno());
return NULL;
}
memset(t, 0, len * sizeof(struct target));
/* split remote:path into remote and path */
for (n = 0; n < len; n++) {
@@ -309,7 +306,7 @@ long atol_with_unit(char *value, bool i)
{
/* value must be "\d+[kKmMgG]?" */
char *u = value + (strlen(optarg) - 1);
char *u = value + (strlen(value) - 1);
long k = i ? 1024 : 1000;
long factor = 1;
long v;
@@ -359,7 +356,6 @@ int main(int argc, char **argv)
struct mscp_ssh_opts s;
struct mscp_opts o;
struct target *t;
int pipe_fd[2];
int ch, n, i, ret;
int direction = 0;
char *remote = NULL, *checkpoint_save = NULL, *checkpoint_load = NULL;
@@ -697,8 +693,13 @@ void print_progress_bar(double percent, char *suffix)
buf[0] = '\0';
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) < 0)
return; /* XXX */
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) < 0 || ws.ws_col == 0) {
// fallback to default
ws.ws_col = 80;
ws.ws_row = 24;
}
bar_width = min(sizeof(buf), ws.ws_col) - strlen(suffix) - 7;
memset(buf, 0, sizeof(buf));
@@ -776,8 +777,6 @@ struct xfer_stat x;
void print_stat(bool final)
{
struct mscp_stats s;
char buf[8192];
int timeout;
gettimeofday(&x.after, NULL);
if (calculate_timedelta(&x.before, &x.after) > 1 || final) {
@@ -793,9 +792,6 @@ void print_stat(bool final)
void *print_stat_thread(void *arg)
{
struct mscp_stats s;
char buf[8192];
memset(&x, 0, sizeof(x));
gettimeofday(&x.start, NULL);
x.before = x.start;

View File

@@ -78,7 +78,7 @@ struct mscp {
static int expand_coremask(const char *coremask, int **cores, int *nr_cores)
{
int n, *core_list, core_list_len = 0, nr_usable, nr_all;
int n, *core_list, nr_usable, nr_all;
char c[2] = { 'x', '\0' };
const char *_coremask;
long v, needle;
@@ -273,7 +273,6 @@ struct mscp *mscp_init(struct mscp_opts *o, struct mscp_ssh_opts *s)
priv_set_errv("bwlimit_init: %s", strerrno());
goto free_out;
}
pr_notice("bitrate limit: %lu bps", o->bitrate);
/* workaround: set libssh using openssh proxyjump
* https://gitlab.com/libssh/libssh-mirror/-/issues/319 */
@@ -563,6 +562,9 @@ int mscp_start(struct mscp *m)
m->opts->nr_threads = n;
}
pr_notice("threads: %d",m->opts->nr_threads);
pr_notice("bwlimit: %ld bps", m->bw.bps);
for (n = 0; n < m->opts->nr_threads; n++) {
t = mscp_copy_thread_spawn(m, n);
if (!t)

View File

@@ -9,7 +9,8 @@ void set_print_severity(int serverity)
{
if (serverity < 0)
__print_severity = -1; /* no print */
__print_severity = serverity;
else
__print_severity = serverity;
}
int get_print_severity()

View File

@@ -114,15 +114,25 @@ static int ssh_set_opts(ssh_session ssh, struct mscp_ssh_opts *opts)
static int ssh_authenticate(ssh_session ssh, struct mscp_ssh_opts *opts)
{
int auth_bit_mask;
static int auth_bit_mask;
int ret;
/* try publickey auth first */
char *p = opts->passphrase ? opts->passphrase : NULL;
if (ssh_userauth_publickey_auto(ssh, NULL, p) == SSH_AUTH_SUCCESS)
return 0;
if (auth_bit_mask == 0) {
/* the first authentication attempt. try none auth to
* get available auth methods. */
if (ssh_userauth_none(ssh, NULL) == SSH_AUTH_SUCCESS)
return 0;
/* save auth_bit_mask for further authentications */
auth_bit_mask = ssh_userauth_list(ssh, NULL);
}
if (auth_bit_mask & SSH_AUTH_METHOD_PUBLICKEY) {
char *p = opts->passphrase ? opts->passphrase : NULL;
if (ssh_userauth_publickey_auto(ssh, NULL, p) == SSH_AUTH_SUCCESS)
return 0;
}
auth_bit_mask = ssh_userauth_list(ssh, NULL);
if (auth_bit_mask & SSH_AUTH_METHOD_PASSWORD) {
if (!opts->password) {
char buf[128] = {};

View File

@@ -9,6 +9,7 @@ import getpass
import datetime
import time
import os
import re
import shutil
from subprocess import check_call, CalledProcessError
@@ -31,6 +32,45 @@ def run2ng(args, env = None, timeout = None, quiet = False):
check_call(cmd, env = env)
@pytest.fixture(autouse=True)
def cleanup_files():
"""
Cleanup files having the following `prefixes` or matching `paths`.
"""
yield
prefixes = [
"src", "dst",
"non_existent_dstdir",
]
paths = [
"/mscp-test-src", "/tmp/mscp-test-src",
"{}/src".format(os.environ["HOME"]),
"{}/dst".format(os.environ["HOME"]),
"/tmp/mscp_test_ssh_config",
"/home/test/dst",
"/home/test/src",
"checkpoint",
]
def remove(path):
print(f"cleanup remove: {fname}")
if os.path.isdir(path):
shutil.rmtree(path)
else:
os.remove(path)
for fname in os.listdir(os.getcwd()):
for prefix in prefixes:
if fname.startswith(prefix):
remove(fname)
break
for path in paths:
if os.path.exists(path):
remove(path)
""" usage test """
@@ -72,8 +112,7 @@ def test_single_copy(mscp, src_prefix, dst_prefix, src, dst):
src.make()
run2ok([mscp, "-vvv", src_prefix + src.path, dst_prefix + dst.path])
assert check_same_md5sum(src, dst)
src.cleanup()
dst.cleanup()
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
def test_failed_to_copy_nonexistent_file(mscp, src_prefix, dst_prefix):
@@ -94,10 +133,6 @@ def test_double_copy(mscp, src_prefix, dst_prefix, s1, s2, d1, d2):
run2ok([mscp, "-vvv", src_prefix + s1.path, src_prefix + s2.path, dst_prefix + "dst"])
assert check_same_md5sum(s1, d1)
assert check_same_md5sum(s2, d2)
s1.cleanup()
s2.cleanup()
d1.cleanup()
d2.cleanup()
remote_v6_prefix = "[::1]:{}/".format(os.getcwd())
@@ -113,10 +148,6 @@ def test_double_copy_with_ipv6_notation(mscp, src_prefix, dst_prefix, s1, s2, d1
src_prefix + s1.path, src_prefix + s2.path, dst_prefix + "dst"])
assert check_same_md5sum(s1, d1)
assert check_same_md5sum(s2, d2)
s1.cleanup()
s2.cleanup()
d1.cleanup()
d2.cleanup()
remote_user_v6_prefix = "{}@[::1]:{}/".format(getpass.getuser(), os.getcwd())
@@ -133,11 +164,6 @@ def test_double_copy_with_user_and_ipv6_notation(mscp, src_prefix, dst_prefix,
src_prefix + s1.path, src_prefix + s2.path, dst_prefix + "dst"])
assert check_same_md5sum(s1, d1)
assert check_same_md5sum(s2, d2)
s1.cleanup()
s2.cleanup()
d1.cleanup()
d2.cleanup()
param_dir_copy = [
@@ -177,10 +203,6 @@ def test_dir_copy(mscp, src_prefix, dst_prefix, src_dir, dst_dir, src, dst, twic
for sf, df in zip(src, twice):
assert check_same_md5sum(sf, df)
for sf, df, tf in zip(src, dst, twice):
sf.cleanup()
df.cleanup()
tf.cleanup()
param_dir_copy_single = [
@@ -196,8 +218,7 @@ def test_dir_copy_single(mscp, src_prefix, dst_prefix, src_dir, dst_dir, src, ds
os.mkdir(dst_dir)
run2ok([mscp, "-vvv", src_prefix + src_dir, dst_prefix + dst_dir])
assert check_same_md5sum(src, dst)
src.cleanup()
dst.cleanup()
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
def test_override_single_file(mscp, src_prefix, dst_prefix):
@@ -208,8 +229,6 @@ def test_override_single_file(mscp, src_prefix, dst_prefix):
run2ok([mscp, "-vvv", src_prefix + src.path, dst_prefix + dst.path])
assert check_same_md5sum(src, dst)
src.cleanup()
dst.cleanup()
absolute_remote_prefix = "localhost:"
param_absolute_remote_prefix = [
@@ -223,8 +242,7 @@ def test_copy_file_under_root_to_dir(mscp, src_prefix, dst_prefix):
run2ok([mscp, "-vvv", src_prefix + src.path,
dst_prefix + os.path.dirname(dst.path)])
assert check_same_md5sum(src, dst)
src.cleanup()
dst.cleanup(preserve_dir = True)
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
def test_dst_has_suffix_slash(mscp, src_prefix, dst_prefix):
@@ -233,7 +251,6 @@ def test_dst_has_suffix_slash(mscp, src_prefix, dst_prefix):
mscp should create dir/ and put dir/src-file-name.
"""
dstdir = "non_existent_dstdir/"
shutil.rmtree(dstdir, ignore_errors=True)
src = File("src", size = 1024 * 1024).make()
dst = File(f"{dstdir}/src")
@@ -242,8 +259,7 @@ def test_dst_has_suffix_slash(mscp, src_prefix, dst_prefix):
dst_prefix + dstdir])
assert check_same_md5sum(src, dst)
src.cleanup()
dst.cleanup()
param_tilde_paths = [
("src", "localhost:~/dst"),
@@ -268,9 +284,6 @@ def test_remote_path_contains_tilde(mscp, src_path, dst_path):
run2ok([mscp, "-vvv", src_path, dst_path])
assert check_same_md5sum(src, dst)
src.cleanup(preserve_dir=True)
dst.cleanup(preserve_dir=True)
def test_remote_path_contains_tilde2(mscp):
src = File("src", size = 1024 * 1024).make()
@@ -279,9 +292,6 @@ def test_remote_path_contains_tilde2(mscp):
run2ok([mscp, "-vvv", src.path, f"localhost:~"])
assert check_same_md5sum(src, dst)
src.cleanup(preserve_dir=True)
dst.cleanup(preserve_dir=True)
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
def test_min_chunk(mscp, src_prefix, dst_prefix):
@@ -291,9 +301,6 @@ def test_min_chunk(mscp, src_prefix, dst_prefix):
run2ok([mscp, "-vvv", "-s", 32768, src_prefix + src.path, dst_prefix + dst.path])
assert check_same_md5sum(src, dst)
src.cleanup()
dst.cleanup()
def is_alpine():
if os.path.exists("/etc/os-release"):
@@ -328,8 +335,7 @@ def test_glob_src_path(mscp, src_prefix, dst_prefix,
run2ok([mscp, "-vvv", src_prefix + src_glob_path, dst_prefix + dst_path])
for src, dst in zip(srcs, dsts):
assert check_same_md5sum(src, dst)
src.cleanup()
dst.cleanup()
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
def test_thread_affinity(mscp, src_prefix, dst_prefix):
@@ -340,8 +346,6 @@ def test_thread_affinity(mscp, src_prefix, dst_prefix):
src_prefix + src.path, dst_prefix + dst.path])
assert check_same_md5sum(src, dst)
src.cleanup()
dst.cleanup()
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
def test_cannot_override_file_with_dir(mscp, src_prefix, dst_prefix):
@@ -350,8 +354,6 @@ def test_cannot_override_file_with_dir(mscp, src_prefix, dst_prefix):
run2ng([mscp, "-vvv", src_prefix + src.path, dst_prefix + "dst/src"])
src.cleanup()
dst.cleanup()
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
def test_transfer_zero_bytes(mscp, src_prefix, dst_prefix):
@@ -359,8 +361,6 @@ def test_transfer_zero_bytes(mscp, src_prefix, dst_prefix):
dst = File("dst")
run2ok([mscp, "-vvv", src_prefix + src.path, dst_prefix + "dst"])
assert os.path.exists("dst")
src.cleanup()
dst.cleanup()
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
def test_override_dst_having_larger_size(mscp, src_prefix, dst_prefix):
@@ -368,8 +368,6 @@ def test_override_dst_having_larger_size(mscp, src_prefix, dst_prefix):
dst = File("dst", size = 1024 * 1024 * 2).make()
run2ok([mscp, "-vvv", src_prefix + src.path, dst_prefix + "dst"])
assert check_same_md5sum(src, dst)
src.cleanup()
dst.cleanup()
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
def test_dont_truncate_dst(mscp, src_prefix, dst_prefix):
@@ -378,7 +376,7 @@ def test_dont_truncate_dst(mscp, src_prefix, dst_prefix):
run2ok([mscp, "-vvv", src_prefix + f.path, dst_prefix + f.path])
md5_after = f.md5sum()
assert md5_before == md5_after
f.cleanup()
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
def test_copy_readonly_file(mscp, src_prefix, dst_prefix):
@@ -392,8 +390,6 @@ def test_copy_readonly_file(mscp, src_prefix, dst_prefix):
dst = File("dst")
run2ok([mscp, "-vvv", src_prefix + src.path, dst_prefix + dst.path])
assert check_same_md5sum(src, dst)
src.cleanup()
dst.cleanup()
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
def test_dont_make_conns_more_than_chunks(mscp, src_prefix, dst_prefix):
@@ -410,8 +406,7 @@ def test_dont_make_conns_more_than_chunks(mscp, src_prefix, dst_prefix):
end = time.time()
for s, d in zip(srcs, dsts):
assert check_same_md5sum(s, d)
shutil.rmtree("src")
shutil.rmtree("dst")
assert((end - start) < 10)
@@ -425,8 +420,6 @@ def test_bwlimit(mscp, src_prefix, dst_prefix):
run2ok([mscp, "-vvv", "-L", "100m", src_prefix + "src", dst_prefix + "dst"])
end = datetime.datetime.now().timestamp()
assert check_same_md5sum(src, dst)
src.cleanup()
dst.cleanup()
assert end - start > 7
@@ -435,14 +428,13 @@ def test_bwlimit(mscp, src_prefix, dst_prefix):
def test_set_port_ng(mscp, src_prefix, dst_prefix, src, dst):
src.make()
run2ng([mscp, "-vvv", "-P", 21, src_prefix + src.path, dst_prefix + dst.path])
src.cleanup()
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
@pytest.mark.parametrize("src, dst", param_single_copy)
def test_set_port_ok(mscp, src_prefix, dst_prefix, src, dst):
src.make()
run2ok([mscp, "-vvv", "-P", 8022, src_prefix + src.path, dst_prefix + dst.path])
src.cleanup()
def test_v4only(mscp):
src = File("src", size = 1024).make()
@@ -450,8 +442,6 @@ def test_v4only(mscp):
dst_prefix = "localhost:{}/".format(os.getcwd())
run2ok([mscp, "-vvv", "-4", src.path, dst_prefix + dst.path])
assert check_same_md5sum(src, dst)
src.cleanup()
dst.cleanup()
def test_v6only(mscp):
src = File("src", size = 1024).make()
@@ -459,22 +449,18 @@ def test_v6only(mscp):
dst_prefix = "ip6-localhost:{}/".format(os.getcwd())
run2ok([mscp, "-vvv", "-6", src.path, dst_prefix + dst.path])
assert check_same_md5sum(src, dst)
src.cleanup()
dst.cleanup()
def test_v4_to_v6_should_fail(mscp):
src = File("src", size = 1024).make()
dst = File("dst")
dst_prefix = "[::1]:{}/".format(os.getcwd())
run2ng([mscp, "-vvv", "-4", src.path, dst_prefix + dst.path])
src.cleanup()
def test_v6_to_v4_should_fail(mscp):
src = File("src", size = 1024).make()
dst = File("dst")
dst_prefix = "127.0.0.1:{}/".format(os.getcwd())
run2ng([mscp, "-vvv", "-6", src.path, dst_prefix + dst.path])
src.cleanup()
def test_quiet_mode(capsys, mscp):
src = File("src", size = 1024).make()
@@ -482,8 +468,7 @@ def test_quiet_mode(capsys, mscp):
dst_prefix = "127.0.0.1:{}/".format(os.getcwd())
run2ok([mscp, "-vvv", "-q", src.path, dst_prefix + dst.path], quiet=True)
assert check_same_md5sum(src, dst)
src.cleanup()
dst.cleanup()
captured = capsys.readouterr()
assert not captured.out
assert not captured.err
@@ -499,8 +484,6 @@ def test_set_conn_interval(mscp, src_prefix, dst_prefix):
for src, dst in zip(srcs, dsts):
assert check_same_md5sum(src, dst)
src.cleanup()
dst.cleanup()
compressions = ["yes", "no", "none"]
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
@@ -510,8 +493,6 @@ def test_compression(mscp, src_prefix, dst_prefix, compress):
dst = File("dst", size = 1024 * 1024 * 2).make()
run2ok([mscp, "-vvv", "-C", compress, src_prefix + src.path, dst_prefix + "dst"])
assert check_same_md5sum(src, dst)
src.cleanup()
dst.cleanup()
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
def test_ccalgo(mscp, src_prefix, dst_prefix):
@@ -548,8 +529,7 @@ def test_config_ok(mscp, src_prefix, dst_prefix):
os.remove(config)
assert check_same_md5sum(src, dst)
src.cleanup()
dst.cleanup()
@pytest.mark.parametrize("src_prefix, dst_prefix", param_testhost_prefix)
def test_config_ng(mscp, src_prefix, dst_prefix):
@@ -563,8 +543,6 @@ def test_config_ng(mscp, src_prefix, dst_prefix):
src_prefix + src.path, dst_prefix + "dst"])
os.remove(config)
src.cleanup()
dst.cleanup()
param_valid_option_ok = [
@@ -581,8 +559,6 @@ def test_inline_option_ok(mscp, src_prefix, dst_prefix, option):
run2ok([mscp, "-vvv"] + option +
[src_prefix + src.path, dst_prefix + dst.path])
assert check_same_md5sum(src, dst)
src.cleanup()
dst.cleanup()
param_valid_option_ng = [
@@ -597,7 +573,6 @@ def test_inline_option_ng(mscp, src_prefix, dst_prefix, option):
dst = File("dst")
run2ng([mscp, "-vvv"] + option +
[src_prefix + src.path, dst_prefix + dst.path])
src.cleanup()
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
@@ -610,8 +585,6 @@ def test_porxyjump_ok(mscp, src_prefix, dst_prefix):
"-J", "localhost:8022",
src_prefix + src.path, dst_prefix + dst.path])
assert check_same_md5sum(src, dst)
src.cleanup()
dst.cleanup()
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
@@ -623,7 +596,6 @@ def test_porxyjump_ng(mscp, src_prefix, dst_prefix):
run2ng([mscp, "-n", 4, "-s", 1024 * 1024, "-vvv",
"-J", "invaliduser@localhost:8022",
src_prefix + src.path, dst_prefix + dst.path])
src.cleanup()
# username test assumes that this test runs inside a container, see Dockerfiles
def test_specify_passphrase_via_env(mscp):
@@ -634,8 +606,6 @@ def test_specify_passphrase_via_env(mscp):
run2ok([mscp, "-vvv", "-l", "test", "-i", "/home/test/.ssh/id_rsa_test",
src.path, "localhost:" + dst.path], env = env)
assert check_same_md5sum(src, dst)
src.cleanup()
dst.cleanup()
def test_specify_invalid_passphrase_via_env(mscp):
src = File(os.getcwd() + "/src", size = 1024).make()
@@ -644,7 +614,6 @@ def test_specify_invalid_passphrase_via_env(mscp):
env["MSCP_SSH_AUTH_PASSPHRASE"] = "invalid-keypassphrase"
run2ng([mscp, "-vvv", "-l", "test", "-i", "/home/test/.ssh/id_rsa_test",
src.path, "localhost:" + dst.path], env = env)
src.cleanup()
def test_specify_password_via_env(mscp):
src = File(os.getcwd() + "/src", size = 1024).make()
@@ -654,8 +623,6 @@ def test_specify_password_via_env(mscp):
run2ok([mscp, "-vvv", "-l", "test",
src.path, "localhost:" + dst.path], env = env)
assert check_same_md5sum(src, dst)
src.cleanup()
dst.cleanup()
def test_specify_invalid_password_via_env(mscp):
src = File(os.getcwd() + "/src", size = 1024).make()
@@ -664,7 +631,44 @@ def test_specify_invalid_password_via_env(mscp):
env["MSCP_SSH_AUTH_PASSWORD"] = "invalid-userpassword"
run2ng([mscp, "-vvv", "-l", "test",
src.path, "localhost:" + dst.path], env = env)
src.cleanup()
@pytest.fixture
def move_pubkey_temporally():
"""
mv ~/.ssh/id_* to id_rsa.bak before test, and move it back after test.
"""
sshdir = os.path.join(os.environ["HOME"], ".ssh")
# move pubkeys to /tmp
moved = []
for fname in os.listdir(sshdir):
if re.match(r"^id_[a-z0-9]+$", fname):
moved.append(fname)
shutil.move(f"{sshdir}/{fname}", f"/tmp/{fname}")
yield
# move back the keys
for fname in moved:
shutil.move(f"/tmp/{fname}", f"{sshdir}/{fname}")
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
def test_passwordauth_without_pubkey(move_pubkey_temporally,
mscp, src_prefix, dst_prefix):
"""
make sure password auth works (by removing public keys)
"""
src = File(os.getcwd() + "/src", size = 1024).make()
dst = File("/home/test/dst")
env = os.environ
env["MSCP_SSH_AUTH_PASSWORD"] = "userpassword"
run2ok([mscp, "-vvv", "-l", "test",
src.path, "localhost:" + dst.path], env = env)
assert check_same_md5sum(src, dst)
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
def test_10k_files(mscp, src_prefix, dst_prefix):
@@ -676,8 +680,6 @@ def test_10k_files(mscp, src_prefix, dst_prefix):
run2ok([mscp, "-v", src_prefix + "src", dst_prefix + "dst"])
for s, d in zip(srcs, dsts):
assert check_same_md5sum(s, d)
shutil.rmtree("src")
shutil.rmtree("dst")
@pytest.mark.parametrize("src_prefix, dst_prefix", param_remote_prefix)
def test_checkpoint_dump_and_resume(mscp, src_prefix, dst_prefix):
@@ -692,10 +694,6 @@ def test_checkpoint_dump_and_resume(mscp, src_prefix, dst_prefix):
run2ok([mscp, "-vvv", "-R", "checkpoint"])
assert check_same_md5sum(src1, dst1)
assert check_same_md5sum(src2, dst2)
src1.cleanup()
src2.cleanup()
dst1.cleanup()
dst2.cleanup()
os.remove("checkpoint")
@pytest.mark.parametrize("timeout", [ 1, 2, 3, 4, 5 ])
@@ -714,10 +712,6 @@ def test_checkpoint_interrupt_large_file(mscp, timeout, src_prefix, dst_prefix):
run2ok([mscp, "-vv", "-R", "checkpoint"])
assert check_same_md5sum(src1, dst1)
assert check_same_md5sum(src2, dst2)
src1.cleanup()
src2.cleanup()
dst1.cleanup()
dst2.cleanup()
os.remove("checkpoint")
@pytest.mark.parametrize("timeout", [ 1, 2, 3, 4, 5 ])
@@ -743,8 +737,6 @@ def test_checkpoint_interrupt_many_files(mscp, timeout, src_prefix, dst_prefix):
for src, dst in files:
assert check_same_md5sum(src, dst)
src.cleanup()
dst.cleanup()
os.remove("checkpoint")