mirror of
https://github.com/upa/mscp.git
synced 2026-02-04 11:34:44 +08:00
mscp copy via python bindings works.
ToDo: memory for struct instance in pymscp.c is not released until mscp.free() is called. It is memory leak in a typical pyhotn usage. Use python extension refcnt instead.
This commit is contained in:
38
mscp/mscp.py
38
mscp/mscp.py
@@ -41,9 +41,9 @@ class mscp:
|
||||
|
||||
def connect(self):
|
||||
if not (self.state == _STATE_INIT or state.state == _STATE_CLEANED):
|
||||
raise RuntimeError("invalid mscp state: {}".format(_state2str()))
|
||||
raise RuntimeError("invalid mscp state: {}".format(self._state2str()))
|
||||
pymscp.mscp_connect(m = self.m)
|
||||
self.state = _CONNECTED
|
||||
self.state = _STATE_CONNECTED
|
||||
|
||||
def add_src_path(self, src_path: str):
|
||||
self.src_paths.append(src_path)
|
||||
@@ -54,8 +54,8 @@ class mscp:
|
||||
pymscp.mscp_set_dst_path(m = self.m, dst_path = dst_path);
|
||||
|
||||
def prepare(self):
|
||||
if self.state != _STATE_CONNCTED:
|
||||
raise RuntimeError("invalid mscp state: {}".format(_state2str()))
|
||||
if self.state != _STATE_CONNECTED:
|
||||
raise RuntimeError("invalid mscp state: {}".format(self._state2str()))
|
||||
if not self.src_paths:
|
||||
raise RuntimeError("src path list is empty")
|
||||
if not self.dst_path:
|
||||
@@ -65,21 +65,21 @@ class mscp:
|
||||
self.state = _STATE_PREPARED
|
||||
|
||||
def start(self):
|
||||
if self.state != STATE_PREPARED:
|
||||
raise RuntimeError("invalid mscp state: {}".format(_state2str()))
|
||||
if self.state != _STATE_PREPARED:
|
||||
raise RuntimeError("invalid mscp state: {}".format(self._state2str()))
|
||||
|
||||
pymscp.mscp_start(m = self.m)
|
||||
self.state = _STATE_RUNNING
|
||||
|
||||
def stop(self):
|
||||
if self.state != _STATE_RUNNING:
|
||||
raise RuntimeError("invalid mscp state: {}".format(_state2str()))
|
||||
raise RuntimeError("invalid mscp state: {}".format(self._state2str()))
|
||||
pymscp.mscp_stop(m = self.m)
|
||||
self.state = _STATE_STOPPED
|
||||
|
||||
def join(self):
|
||||
if not (self.state == STATE_RUNNING or self.state == _STATE_STOPPED):
|
||||
raise RuntimeError("invalid mscp state: {}".format(_state2str()))
|
||||
if not (self.state == _STATE_RUNNING or self.state == _STATE_STOPPED):
|
||||
raise RuntimeError("invalid mscp state: {}".format(self._state2str()))
|
||||
pymscp.mscp_join(m = self.m)
|
||||
self.state = _STATE_JOINED
|
||||
|
||||
@@ -87,15 +87,15 @@ class mscp:
|
||||
return pymscp.mscp_get_stats(m = self.m)
|
||||
|
||||
def cleanup(self):
|
||||
if self.state != _STATE_JOIND:
|
||||
raise RuntimeError("invalid mscp state: {}".format(_state2str()))
|
||||
pymscp.mscp_cleanup()
|
||||
self.state = _STATE_CLEAND
|
||||
if self.state != _STATE_JOINED:
|
||||
raise RuntimeError("invalid mscp state: {}".format(self._state2str()))
|
||||
pymscp.mscp_cleanup(m = self.m)
|
||||
self.state = _STATE_CLEANED
|
||||
|
||||
def free(self):
|
||||
if self.state != _STATE_CLEANED:
|
||||
raise RuntimeError("invalid mscp state: {}".format(_state2str()))
|
||||
pymscp.mscp_free()
|
||||
raise RuntimeError("invalid mscp state: {}".format(self._state2str()))
|
||||
pymscp.mscp_free(m = self.m)
|
||||
|
||||
|
||||
# Simple interface: mscp.copy(src, dst)
|
||||
@@ -104,17 +104,19 @@ class mscp:
|
||||
self.connect()
|
||||
|
||||
if type(src) == list:
|
||||
self.src_paths += src
|
||||
for path in src:
|
||||
self.add_src_path(path)
|
||||
elif type(src) == str:
|
||||
self.src_paths.append(src)
|
||||
self.add_src_path(src)
|
||||
else:
|
||||
raise ValueError("src must be str of list: '{}'".format(src))
|
||||
|
||||
self.dst_path = dst
|
||||
self.set_dst_path(dst)
|
||||
|
||||
self.prepare()
|
||||
self.start()
|
||||
if nonblock:
|
||||
return
|
||||
|
||||
self.join()
|
||||
self.cleanup()
|
||||
|
||||
196
src/pymscp.c
196
src/pymscp.c
@@ -1,5 +1,8 @@
|
||||
#define PY_SSIZE_T_CLEAN
|
||||
#include <Python.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <mscp.h>
|
||||
|
||||
/*
|
||||
@@ -12,14 +15,20 @@
|
||||
#define MAX_MSCP_INSTS 16
|
||||
|
||||
/* XXX: cut corners */
|
||||
struct mscp *insts[MAX_MSCP_INSTS];
|
||||
struct instance {
|
||||
struct mscp_opts mo;
|
||||
struct mscp_ssh_opts so;
|
||||
struct mscp *m;
|
||||
};
|
||||
|
||||
static int add_mscp_inst(struct mscp *m)
|
||||
struct instance *insts[MAX_MSCP_INSTS];
|
||||
|
||||
static int add_instance(struct instance *i)
|
||||
{
|
||||
int n;
|
||||
for (n = 0; n < MAX_MSCP_INSTS; n++) {
|
||||
if (insts[n] == NULL) {
|
||||
insts[n] = m;
|
||||
insts[n] = i;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -27,26 +36,38 @@ static int add_mscp_inst(struct mscp *m)
|
||||
return -1; /* full of mscp instances */
|
||||
}
|
||||
|
||||
static struct mscp *get_mscp_inst(unsigned long long maddr)
|
||||
static struct instance *get_instance(unsigned long long addr)
|
||||
{
|
||||
int n;
|
||||
for (n = 0; n < MAX_MSCP_INSTS; n++) {
|
||||
if (insts[n] == (void *)maddr)
|
||||
if (insts[n] == (void *)addr)
|
||||
return insts[n];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int release_mscp_inst(struct mscp *m)
|
||||
static struct mscp *get_mscp(unsigned long long addr)
|
||||
{
|
||||
struct instance *i = get_instance(addr);
|
||||
|
||||
if (!i)
|
||||
return NULL;
|
||||
return i->m;
|
||||
}
|
||||
|
||||
static int release_instance(struct instance *i)
|
||||
{
|
||||
int n;
|
||||
for (n = 0; n < MAX_MSCP_INSTS; n++) {
|
||||
if (insts[n] == m) {
|
||||
if (insts[n] == i) {
|
||||
insts[n] = NULL;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
free(i);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -89,32 +110,35 @@ static PyObject *wrap_mscp_init(PyObject *sef, PyObject *args, PyObject *kw)
|
||||
"enable_nagle", /* bool */
|
||||
NULL,
|
||||
};
|
||||
const char *fmt = "si" "|iikkkzii" "zzzzzzzzipp";
|
||||
const char *fmt = "si" "|iikkksii" "ssssssssipp";
|
||||
char *coremask = NULL;
|
||||
char *login_name = NULL, *port = NULL, *identity = NULL;
|
||||
char *cipher = NULL, *hmac = NULL, *compress = NULL;
|
||||
char *password = NULL, *passphrase = NULL;
|
||||
|
||||
struct mscp_ssh_opts so;
|
||||
struct mscp_opts mo;
|
||||
struct mscp *m;
|
||||
struct instance *i;
|
||||
int direction;
|
||||
int ret;
|
||||
|
||||
memset(&mo, 0, sizeof(mo));
|
||||
memset(&so, 0, sizeof(so));
|
||||
i = malloc(sizeof(*i));
|
||||
if (!i) {
|
||||
PyErr_Format(PyExc_RuntimeError, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(i, 0, sizeof(*i));
|
||||
|
||||
ret = PyArg_ParseTupleAndKeywords(args, kw, fmt, keywords,
|
||||
&remote,
|
||||
&direction,
|
||||
&mo.nr_threads,
|
||||
&mo.nr_ahead,
|
||||
&mo.min_chunk_sz,
|
||||
&mo.max_chunk_sz,
|
||||
&mo.buf_sz,
|
||||
&i->mo.nr_threads,
|
||||
&i->mo.nr_ahead,
|
||||
&i->mo.min_chunk_sz,
|
||||
&i->mo.max_chunk_sz,
|
||||
&i->mo.buf_sz,
|
||||
&coremask,
|
||||
&mo.severity,
|
||||
&mo.msg_fd,
|
||||
&i->mo.severity,
|
||||
&i->mo.msg_fd,
|
||||
&login_name,
|
||||
&port,
|
||||
&identity,
|
||||
@@ -123,58 +147,60 @@ static PyObject *wrap_mscp_init(PyObject *sef, PyObject *args, PyObject *kw)
|
||||
&compress,
|
||||
&password,
|
||||
&passphrase,
|
||||
&so.debug_level,
|
||||
&so.no_hostkey_check,
|
||||
&so.enable_nagle);
|
||||
&i->so.debug_level,
|
||||
&i->so.no_hostkey_check,
|
||||
&i->so.enable_nagle);
|
||||
|
||||
if (!ret)
|
||||
return NULL;
|
||||
|
||||
if (coremask)
|
||||
strncpy(mo.coremask, coremask, MSCP_MAX_COREMASK_STR - 1);
|
||||
strncpy(i->mo.coremask, coremask, MSCP_MAX_COREMASK_STR - 1);
|
||||
if (login_name)
|
||||
strncpy(so.login_name, login_name, MSCP_SSH_MAX_LOGIN_NAME - 1);
|
||||
strncpy(i->so.login_name, login_name, MSCP_SSH_MAX_LOGIN_NAME - 1);
|
||||
if (port)
|
||||
strncpy(so.port, port, MSCP_SSH_MAX_PORT_STR - 1);
|
||||
strncpy(i->so.port, port, MSCP_SSH_MAX_PORT_STR - 1);
|
||||
if (identity)
|
||||
strncpy(so.identity, identity, MSCP_SSH_MAX_IDENTITY_PATH - 1);
|
||||
strncpy(i->so.identity, identity, MSCP_SSH_MAX_IDENTITY_PATH - 1);
|
||||
if (cipher)
|
||||
strncpy(so.cipher, cipher, MSCP_SSH_MAX_CIPHER_STR - 1);
|
||||
strncpy(i->so.cipher, cipher, MSCP_SSH_MAX_CIPHER_STR - 1);
|
||||
if (hmac)
|
||||
strncpy(so.hmac, hmac, MSCP_SSH_MAX_HMAC_STR - 1);
|
||||
strncpy(i->so.hmac, hmac, MSCP_SSH_MAX_HMAC_STR - 1);
|
||||
if (compress)
|
||||
strncpy(so.compress, compress, MSCP_SSH_MAX_COMP_STR - 1);
|
||||
strncpy(i->so.compress, compress, MSCP_SSH_MAX_COMP_STR - 1);
|
||||
if (password)
|
||||
strncpy(so.password, password, MSCP_SSH_MAX_PASSWORD - 1);
|
||||
strncpy(i->so.password, password, MSCP_SSH_MAX_PASSWORD - 1);
|
||||
if (passphrase)
|
||||
strncpy(so.passphrase, passphrase, MSCP_SSH_MAX_PASSPHRASE - 1);
|
||||
strncpy(i->so.passphrase, passphrase, MSCP_SSH_MAX_PASSPHRASE - 1);
|
||||
|
||||
|
||||
m = mscp_init(remote, direction, &mo, &so);
|
||||
if (!m)
|
||||
return NULL;
|
||||
|
||||
if (add_mscp_inst(m) < 0) {
|
||||
PyErr_Format(PyExc_RuntimeError, "too many mscp isntances");
|
||||
mscp_free(m);
|
||||
i->m = mscp_init(remote, direction, &i->mo, &i->so);
|
||||
if (!i->m) {
|
||||
free(i);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return Py_BuildValue("K", (unsigned long long)m);
|
||||
if (add_instance(i) < 0) {
|
||||
PyErr_Format(PyExc_RuntimeError, "too many mscp isntances");
|
||||
mscp_free(i->m);
|
||||
free(i);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return Py_BuildValue("K", (unsigned long long)i);
|
||||
}
|
||||
|
||||
static PyObject *wrap_mscp_connect(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
char *keywords[] = { "m", NULL };
|
||||
unsigned long long maddr;
|
||||
unsigned long long addr;
|
||||
struct mscp *m;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "K", keywords, &maddr))
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "K", keywords, &addr))
|
||||
return NULL;
|
||||
|
||||
m = get_mscp_inst(maddr);
|
||||
m = get_mscp(addr);
|
||||
if (!m) {
|
||||
PyErr_Format(PyExc_RuntimeError, "invalid mscp address");
|
||||
PyErr_Format(PyExc_RuntimeError, "invalid mscp instance address");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -189,16 +215,16 @@ static PyObject *wrap_mscp_connect(PyObject *self, PyObject *args, PyObject *kw)
|
||||
static PyObject *wrap_mscp_add_src_path(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
char *keywords[] = { "m", "src_path", NULL };
|
||||
unsigned long long maddr;
|
||||
unsigned long long addr;
|
||||
char *src_path;
|
||||
struct mscp *m;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "Ks", keywords, &maddr, &src_path))
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "Ks", keywords, &addr, &src_path))
|
||||
return NULL;
|
||||
|
||||
m = get_mscp_inst(maddr);
|
||||
m = get_mscp(addr);
|
||||
if (!m) {
|
||||
PyErr_Format(PyExc_RuntimeError, "invalid mscp address");
|
||||
PyErr_Format(PyExc_RuntimeError, "invalid mscp instance address");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -213,16 +239,16 @@ static PyObject *wrap_mscp_add_src_path(PyObject *self, PyObject *args, PyObject
|
||||
static PyObject *wrap_mscp_set_dst_path(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
char *keywords[] = { "m", "dst_path", NULL };
|
||||
unsigned long long maddr;
|
||||
unsigned long long addr;
|
||||
char *dst_path;
|
||||
struct mscp *m;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "Ks", keywords, &maddr, &dst_path))
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "Ks", keywords, &addr, &dst_path))
|
||||
return NULL;
|
||||
|
||||
m = get_mscp_inst(maddr);
|
||||
m = get_mscp(addr);
|
||||
if (!m) {
|
||||
PyErr_Format(PyExc_RuntimeError, "invalid mscp address");
|
||||
PyErr_Format(PyExc_RuntimeError, "invalid mscp instance address");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -237,15 +263,15 @@ static PyObject *wrap_mscp_set_dst_path(PyObject *self, PyObject *args, PyObject
|
||||
static PyObject *wrap_mscp_prepare(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
char *keywords[] = { "m", NULL };
|
||||
unsigned long long maddr;
|
||||
unsigned long long addr;
|
||||
struct mscp *m;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "K", keywords, &maddr))
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "K", keywords, &addr))
|
||||
return NULL;
|
||||
|
||||
m = get_mscp_inst(maddr);
|
||||
m = get_mscp(addr);
|
||||
if (!m) {
|
||||
PyErr_Format(PyExc_RuntimeError, "invalid mscp address");
|
||||
PyErr_Format(PyExc_RuntimeError, "invalid mscp instance address");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -260,15 +286,15 @@ static PyObject *wrap_mscp_prepare(PyObject *self, PyObject *args, PyObject *kw)
|
||||
static PyObject *wrap_mscp_start(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
char *keywords[] = { "m", NULL };
|
||||
unsigned long long maddr;
|
||||
unsigned long long addr;
|
||||
struct mscp *m;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "K", keywords, &maddr))
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "K", keywords, &addr))
|
||||
return NULL;
|
||||
|
||||
m = get_mscp_inst(maddr);
|
||||
m = get_mscp(addr);
|
||||
if (!m) {
|
||||
PyErr_Format(PyExc_RuntimeError, "invalid mscp address");
|
||||
PyErr_Format(PyExc_RuntimeError, "invalid mscp instance address");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -283,15 +309,15 @@ static PyObject *wrap_mscp_start(PyObject *self, PyObject *args, PyObject *kw)
|
||||
static PyObject *wrap_mscp_stop(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
char *keywords[] = { "m", NULL };
|
||||
unsigned long long maddr;
|
||||
unsigned long long addr;
|
||||
struct mscp *m;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "K", keywords, &maddr))
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "K", keywords, &addr))
|
||||
return NULL;
|
||||
|
||||
m = get_mscp_inst(maddr);
|
||||
m = get_mscp(addr);
|
||||
if (!m) {
|
||||
PyErr_Format(PyExc_RuntimeError, "invalid mscp address");
|
||||
PyErr_Format(PyExc_RuntimeError, "invalid mscp instance address");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -303,15 +329,15 @@ static PyObject *wrap_mscp_stop(PyObject *self, PyObject *args, PyObject *kw)
|
||||
static PyObject *wrap_mscp_join(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
char *keywords[] = { "m", NULL };
|
||||
unsigned long long maddr;
|
||||
unsigned long long addr;
|
||||
struct mscp *m;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "K", keywords, &maddr))
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "K", keywords, &addr))
|
||||
return NULL;
|
||||
|
||||
m = get_mscp_inst(maddr);
|
||||
m = get_mscp(addr);
|
||||
if (!m) {
|
||||
PyErr_Format(PyExc_RuntimeError, "invalid mscp address");
|
||||
PyErr_Format(PyExc_RuntimeError, "invalid mscp instance address");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -326,16 +352,16 @@ static PyObject *wrap_mscp_join(PyObject *self, PyObject *args, PyObject *kw)
|
||||
static PyObject *wrap_mscp_get_stats(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
char *keywords[] = { "m", NULL };
|
||||
unsigned long long maddr;
|
||||
unsigned long long addr;
|
||||
struct mscp_stats s;
|
||||
struct mscp *m;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "K", keywords, &maddr))
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "K", keywords, &addr))
|
||||
return NULL;
|
||||
|
||||
m = get_mscp_inst(maddr);
|
||||
m = get_mscp(addr);
|
||||
if (!m) {
|
||||
PyErr_Format(PyExc_RuntimeError, "invalid mscp address");
|
||||
PyErr_Format(PyExc_RuntimeError, "invalid mscp instance address");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -347,15 +373,15 @@ static PyObject *wrap_mscp_get_stats(PyObject *self, PyObject *args, PyObject *k
|
||||
static PyObject *wrap_mscp_cleanup(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
char *keywords[] = { "m", NULL };
|
||||
unsigned long long maddr;
|
||||
unsigned long long addr;
|
||||
struct mscp *m;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "K", keywords, &maddr))
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "K", keywords, &addr))
|
||||
return NULL;
|
||||
|
||||
m = get_mscp_inst(maddr);
|
||||
m = get_mscp(addr);
|
||||
if (!m) {
|
||||
PyErr_Format(PyExc_RuntimeError, "invalid mscp address");
|
||||
PyErr_Format(PyExc_RuntimeError, "invalid mscp instance address");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -367,20 +393,20 @@ static PyObject *wrap_mscp_cleanup(PyObject *self, PyObject *args, PyObject *kw)
|
||||
static PyObject *wrap_mscp_free(PyObject *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
char *keywords[] = { "m", NULL };
|
||||
unsigned long long maddr;
|
||||
struct mscp *m;
|
||||
unsigned long long addr;
|
||||
struct instance *i;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "K", keywords, &maddr))
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "K", keywords, &addr))
|
||||
return NULL;
|
||||
|
||||
m = get_mscp_inst(maddr);
|
||||
if (!m) {
|
||||
PyErr_Format(PyExc_RuntimeError, "invalid mscp address");
|
||||
i = get_instance(addr);
|
||||
if (!i) {
|
||||
PyErr_Format(PyExc_RuntimeError, "invalid mscp instance address");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
release_mscp_inst(m);
|
||||
mscp_free(m);
|
||||
mscp_free(i->m);
|
||||
release_instance(i);
|
||||
|
||||
return Py_BuildValue("");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user