The branch, master has been updated via 9e6070b s3-pylibsmb: Add get_oplock_break via ff68408 s3-pylibsmb: Factor out py_tevent_cond_signal via d0a0fb3 s3-pylibsmb: Reduce the number of warnings via 7305660 s3: Convert cli_oplock_break_waiter to smbXcli via 982ddc4 s3: Add "readdir" to pylibsmb via a272635 s3: Fix some nonempty line endings via e0fdeda s3-pylibsmb: move py_tevent_req_wait_exc up in the file via 9475205 s3-pylibsmb: Factor out py_tevent_cond_wait from 8e5f30c build: Remove unused define UNIXWARE
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 9e6070b5fcc17f0e866367c4d3f4dfcb95be6c46 Author: Volker Lendecke <v...@samba.org> Date: Sat Sep 22 10:45:32 2012 -0700 s3-pylibsmb: Add get_oplock_break Autobuild-User(master): Volker Lendecke <v...@samba.org> Autobuild-Date(master): Sun Sep 23 18:01:28 CEST 2012 on sn-devel-104 commit ff6840815d6e6252aa3fa27a4f04d992ab912d14 Author: Volker Lendecke <v...@samba.org> Date: Sat Sep 22 10:40:06 2012 -0700 s3-pylibsmb: Factor out py_tevent_cond_signal commit d0a0fb32929e26ea9dd30cb3e2cacff03f68b9d2 Author: Volker Lendecke <v...@samba.org> Date: Sat Sep 22 10:38:46 2012 -0700 s3-pylibsmb: Reduce the number of warnings commit 7305660c1139fc1d2dc40fb3324855ec7381eac5 Author: Volker Lendecke <v...@samba.org> Date: Sat Sep 22 18:57:47 2012 +0200 s3: Convert cli_oplock_break_waiter to smbXcli commit 982ddc478551c3eb11a6d01acaea22fb60743d2a Author: Volker Lendecke <v...@samba.org> Date: Mon Aug 20 14:38:42 2012 +0200 s3: Add "readdir" to pylibsmb commit a272635b792a806f589cd5a6a3a345cdc855b4be Author: Volker Lendecke <v...@samba.org> Date: Tue Sep 18 16:19:07 2012 -0700 s3: Fix some nonempty line endings commit e0fdeda86cfc75cfe2bdd7dffeef7fc9e173c8aa Author: Christian Ambach <a...@samba.org> Date: Sun Sep 16 11:39:26 2012 -0700 s3-pylibsmb: move py_tevent_req_wait_exc up in the file this is needed to be able to use it in other functions and spares the prototype Pair-Programmed-With: Volker Lendecke <v...@samba.org> commit 947520521ed3da2f0787e17a9fe906024fdee7e3 Author: Volker Lendecke <v...@samba.org> Date: Fri Sep 21 12:05:04 2012 -0700 s3-pylibsmb: Factor out py_tevent_cond_wait ----------------------------------------------------------------------- Summary of changes: source3/libsmb/clioplock.c | 31 +++-- source3/libsmb/pylibsmb.c | 317 +++++++++++++++++++++++++++++++++++++------- 2 files changed, 291 insertions(+), 57 deletions(-) Changeset truncated at 500 lines: diff --git a/source3/libsmb/clioplock.c b/source3/libsmb/clioplock.c index 0b3ca2c..d9ab414 100644 --- a/source3/libsmb/clioplock.c +++ b/source3/libsmb/clioplock.c @@ -1,18 +1,18 @@ -/* +/* Unix SMB/CIFS implementation. SMB client oplock functions Copyright (C) Andrew Tridgell 2001 - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ @@ -47,7 +47,8 @@ struct tevent_req *cli_smb_oplock_break_waiter_send(TALLOC_CTX *mem_ctx, * Create a fake SMB request that we will never send out. This is only * used to be set into the pending queue with the right mid. */ - subreq = cli_smb_req_create(mem_ctx, ev, cli, 0, 0, 0, NULL, 0, NULL); + subreq = smb1cli_req_create(mem_ctx, ev, cli->conn, 0, 0, 0, 0, 0, 0, + 0, NULL, NULL, 0, NULL, 0, NULL); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); } @@ -67,19 +68,31 @@ static void cli_smb_oplock_break_waiter_done(struct tevent_req *subreq) subreq, struct tevent_req); struct cli_smb_oplock_break_waiter_state *state = tevent_req_data( req, struct cli_smb_oplock_break_waiter_state); + struct iovec *iov; uint8_t wct; uint16_t *vwv; - uint32_t num_bytes; - uint8_t *bytes; NTSTATUS status; - status = cli_smb_recv(subreq, state, NULL, 8, &wct, &vwv, - &num_bytes, &bytes); + status = smb1cli_req_recv(subreq, state, + &iov, /* piov */ + NULL, /* phdr */ + &wct, + &vwv, + NULL, /* pvwv_offset */ + NULL, /* pnum_bytes */ + NULL, /* pbytes */ + NULL, /* pbytes_offset */ + NULL, /* pinbuf */ + NULL, 0); /* expected */ TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { tevent_req_nterror(req, status); return; } + if (wct < 8) { + tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); + return; + } state->fnum = SVAL(vwv+2, 0); state->level = CVAL(vwv+3, 1); tevent_req_done(req); diff --git a/source3/libsmb/pylibsmb.c b/source3/libsmb/pylibsmb.c index d31409c..e357d0f 100644 --- a/source3/libsmb/pylibsmb.c +++ b/source3/libsmb/pylibsmb.c @@ -25,6 +25,7 @@ #include "system/select.h" #include "source4/libcli/util/pyerrors.h" #include "auth/credentials/pycredentials.h" +#include "trans2.h" static PyTypeObject *get_pytype(const char *module, const char *type) { @@ -49,13 +50,40 @@ static PyTypeObject *get_pytype(const char *module, const char *type) return result; } +/* + * We're using "const char **" for keywords, + * PyArg_ParseTupleAndKeywords expects a "char **". Confine the + * inevitable warnings to just one place. + */ +static int ParseTupleAndKeywords(PyObject *args, PyObject *kw, + const char *format, const char **keywords, + ...) +{ + va_list a; + int ret; + va_start(a, keywords); + ret = PyArg_VaParseTupleAndKeywords(args, kw, format, + (char **)keywords, a); + va_end(a); + return ret; +} + struct py_cli_thread; +struct py_cli_oplock_break { + uint16_t fnum; + uint8_t level; +}; + struct py_cli_state { PyObject_HEAD struct cli_state *cli; struct tevent_context *ev; struct py_cli_thread *thread_state; + + struct tevent_req *oplock_waiter; + struct py_cli_oplock_break *oplock_breaks; + struct py_tevent_cond *oplock_cond; }; #if HAVE_PTHREAD @@ -228,33 +256,30 @@ struct py_tevent_cond { static void py_tevent_signalme(struct tevent_req *req); -static int py_tevent_req_wait(struct tevent_context *ev, - struct tevent_req *req) +static int py_tevent_cond_wait(struct py_tevent_cond *cond) { - struct py_tevent_cond cond; int ret, result; - result = pthread_mutex_init(&cond.mutex, NULL); + result = pthread_mutex_init(&cond->mutex, NULL); if (result != 0) { goto fail; } - result = pthread_cond_init(&cond.cond, NULL); + result = pthread_cond_init(&cond->cond, NULL); if (result != 0) { goto fail_mutex; } - cond.is_done = false; - tevent_req_set_callback(req, py_tevent_signalme, &cond); - - result = pthread_mutex_lock(&cond.mutex); + result = pthread_mutex_lock(&cond->mutex); if (result != 0) { goto fail_cond; } - while (!cond.is_done) { + cond->is_done = false; + + while (!cond->is_done) { Py_BEGIN_ALLOW_THREADS - result = pthread_cond_wait(&cond.cond, &cond.mutex); + result = pthread_cond_wait(&cond->cond, &cond->mutex); Py_END_ALLOW_THREADS if (result != 0) { @@ -263,22 +288,28 @@ static int py_tevent_req_wait(struct tevent_context *ev, } fail_unlock: - ret = pthread_mutex_unlock(&cond.mutex); + ret = pthread_mutex_unlock(&cond->mutex); assert(ret == 0); fail_cond: - ret = pthread_cond_destroy(&cond.cond); + ret = pthread_cond_destroy(&cond->cond); assert(ret == 0); fail_mutex: - ret = pthread_mutex_destroy(&cond.mutex); + ret = pthread_mutex_destroy(&cond->mutex); assert(ret == 0); fail: return result; } -static void py_tevent_signalme(struct tevent_req *req) +static int py_tevent_req_wait(struct tevent_context *ev, + struct tevent_req *req) +{ + struct py_tevent_cond cond; + tevent_req_set_callback(req, py_tevent_signalme, &cond); + return py_tevent_cond_wait(&cond); +} + +static void py_tevent_cond_signal(struct py_tevent_cond *cond) { - struct py_tevent_cond *cond = (struct py_tevent_cond *) - tevent_req_callback_data_void(req); int ret; ret = pthread_mutex_lock(&cond->mutex); @@ -292,6 +323,14 @@ static void py_tevent_signalme(struct tevent_req *req) assert(ret == 0); } +static void py_tevent_signalme(struct tevent_req *req) +{ + struct py_tevent_cond *cond = (struct py_tevent_cond *) + tevent_req_callback_data_void(req); + + py_tevent_cond_signal(cond); +} + #else static bool py_cli_state_setup_ev(struct py_cli_state *self) @@ -316,6 +355,25 @@ static int py_tevent_req_wait(struct tevent_context *ev, #endif +static bool py_tevent_req_wait_exc(struct tevent_context *ev, + struct tevent_req *req) +{ + int ret; + + if (req == NULL) { + PyErr_NoMemory(); + return false; + } + ret = py_tevent_req_wait(ev, req); + if (ret != 0) { + TALLOC_FREE(req); + errno = ret; + PyErr_SetFromErrno(PyExc_RuntimeError); + return false; + } + return true; +} + static PyObject *py_cli_state_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { @@ -328,9 +386,14 @@ static PyObject *py_cli_state_new(PyTypeObject *type, PyObject *args, self->cli = NULL; self->ev = NULL; self->thread_state = NULL; + self->oplock_waiter = NULL; + self->oplock_cond = NULL; + self->oplock_breaks = NULL; return (PyObject *)self; } +static void py_cli_got_oplock_break(struct tevent_req *req); + static int py_cli_state_init(struct py_cli_state *self, PyObject *args, PyObject *kwds) { @@ -350,8 +413,8 @@ static int py_cli_state_init(struct py_cli_state *self, PyObject *args, return -1; } - ret = PyArg_ParseTupleAndKeywords( - args, kwds, "ss|O!", (char **)kwlist, + ret = ParseTupleAndKeywords( + args, kwds, "ss|O!", kwlist, &host, &share, py_type_Credentials, &creds); Py_DECREF(py_type_Credentials); @@ -380,38 +443,123 @@ static int py_cli_state_init(struct py_cli_state *self, PyObject *args, PyErr_SetNTSTATUS(status); return -1; } + + self->oplock_waiter = cli_smb_oplock_break_waiter_send( + self->ev, self->ev, self->cli); + if (self->oplock_waiter == NULL) { + PyErr_NoMemory(); + return -1; + } + tevent_req_set_callback(self->oplock_waiter, py_cli_got_oplock_break, + self); return 0; } -static void py_cli_state_dealloc(struct py_cli_state *self) +static void py_cli_got_oplock_break(struct tevent_req *req) { - TALLOC_FREE(self->thread_state); - TALLOC_FREE(self->ev); + struct py_cli_state *self = (struct py_cli_state *) + tevent_req_callback_data_void(req); + struct py_cli_oplock_break b; + struct py_cli_oplock_break *tmp; + size_t num_breaks; + NTSTATUS status; - if (self->cli != NULL) { - cli_shutdown(self->cli); - self->cli = NULL; + status = cli_smb_oplock_break_waiter_recv(req, &b.fnum, &b.level); + TALLOC_FREE(req); + self->oplock_waiter = NULL; + + if (!NT_STATUS_IS_OK(status)) { + return; } - self->ob_type->tp_free((PyObject *)self); + + num_breaks = talloc_array_length(self->oplock_breaks); + tmp = talloc_realloc(self->ev, self->oplock_breaks, + struct py_cli_oplock_break, num_breaks+1); + if (tmp == NULL) { + return; + } + self->oplock_breaks = tmp; + self->oplock_breaks[num_breaks] = b; + + if (self->oplock_cond != NULL) { + py_tevent_cond_signal(self->oplock_cond); + } + + self->oplock_waiter = cli_smb_oplock_break_waiter_send( + self->ev, self->ev, self->cli); + if (self->oplock_waiter == NULL) { + return; + } + tevent_req_set_callback(self->oplock_waiter, py_cli_got_oplock_break, + self); } -static bool py_tevent_req_wait_exc(struct tevent_context *ev, - struct tevent_req *req) +static PyObject *py_cli_get_oplock_break(struct py_cli_state *self, + PyObject *args) { - int ret; + size_t num_oplock_breaks; - if (req == NULL) { - PyErr_NoMemory(); - return false; + if (!PyArg_ParseTuple(args, "")) { + return NULL; } - ret = py_tevent_req_wait(ev, req); - if (ret != 0) { - TALLOC_FREE(req); - errno = ret; + + if (self->oplock_cond != NULL) { + errno = EBUSY; PyErr_SetFromErrno(PyExc_RuntimeError); - return false; + return NULL; } - return true; + + num_oplock_breaks = talloc_array_length(self->oplock_breaks); + + if (num_oplock_breaks == 0) { + struct py_tevent_cond cond; + int ret; + + self->oplock_cond = &cond; + ret = py_tevent_cond_wait(&cond); + self->oplock_cond = NULL; + + if (ret != 0) { + errno = ret; + PyErr_SetFromErrno(PyExc_RuntimeError); + return NULL; + } + } + + num_oplock_breaks = talloc_array_length(self->oplock_breaks); + if (num_oplock_breaks > 0) { + PyObject *result; + + result = Py_BuildValue( + "{s:i,s:i}", + "fnum", self->oplock_breaks[0].fnum, + "level", self->oplock_breaks[0].level); + + memmove(&self->oplock_breaks[0], &self->oplock_breaks[1], + sizeof(self->oplock_breaks[0]) * + (num_oplock_breaks - 1)); + self->oplock_breaks = talloc_realloc( + NULL, self->oplock_breaks, struct py_cli_oplock_break, + num_oplock_breaks - 1); + + return result; + } + + Py_INCREF(Py_None); + return Py_None; +} + +static void py_cli_state_dealloc(struct py_cli_state *self) +{ + TALLOC_FREE(self->thread_state); + TALLOC_FREE(self->oplock_waiter); + TALLOC_FREE(self->ev); + + if (self->cli != NULL) { + cli_shutdown(self->cli); + self->cli = NULL; + } + self->ob_type->tp_free((PyObject *)self); } static PyObject *py_cli_create(struct py_cli_state *self, PyObject *args, @@ -434,8 +582,8 @@ static PyObject *py_cli_create(struct py_cli_state *self, PyObject *args, "ShareAccess", "CreateDisposition", "CreateOptions", "SecurityFlags", NULL }; - if (!PyArg_ParseTupleAndKeywords( - args, kwds, "s|IIIIIII", (char **)kwlist, + if (!ParseTupleAndKeywords( + args, kwds, "s|IIIIIII", kwlist, &fname, &CreateFlags, &DesiredAccess, &FileAttributes, &ShareAccess, &CreateDisposition, &CreateOptions, &SecurityFlags)) { @@ -499,8 +647,8 @@ static PyObject *py_cli_write(struct py_cli_state *self, PyObject *args, static const char *kwlist[] = { "fnum", "buffer", "offset", "mode", NULL }; - if (!PyArg_ParseTupleAndKeywords( - args, kwds, "Is#K|I", (char **)kwlist, + if (!ParseTupleAndKeywords( + args, kwds, "Is#K|I", kwlist, &fnum, &buf, &buflen, &offset, &mode)) { return NULL; } @@ -535,8 +683,8 @@ static PyObject *py_cli_read(struct py_cli_state *self, PyObject *args, static const char *kwlist[] = { "fnum", "offset", "size", NULL }; - if (!PyArg_ParseTupleAndKeywords( - args, kwds, "IKI", (char **)kwlist, &fnum, &offset, + if (!ParseTupleAndKeywords( + args, kwds, "IKI", kwlist, &fnum, &offset, &size)) { return NULL; } @@ -569,8 +717,8 @@ static PyObject *py_cli_ftruncate(struct py_cli_state *self, PyObject *args, static const char *kwlist[] = { "fnum", "size", NULL }; - if (!PyArg_ParseTupleAndKeywords( - args, kwds, "IK", (char **)kwlist, &fnum, &size)) { + if (!ParseTupleAndKeywords( + args, kwds, "IK", kwlist, &fnum, &size)) { return NULL; } @@ -600,8 +748,8 @@ static PyObject *py_cli_delete_on_close(struct py_cli_state *self, static const char *kwlist[] = { "fnum", "flag", NULL }; - if (!PyArg_ParseTupleAndKeywords( - args, kwds, "II", (char **)kwlist, &fnum, &flag)) { + if (!ParseTupleAndKeywords( + args, kwds, "II", kwlist, &fnum, &flag)) { return NULL; } @@ -621,6 +769,74 @@ static PyObject *py_cli_delete_on_close(struct py_cli_state *self, return Py_None; } +static PyObject *py_cli_list(struct py_cli_state *self, + PyObject *args, + PyObject *kwds) +{ + char *mask; + unsigned attribute = + FILE_ATTRIBUTE_DIRECTORY | + FILE_ATTRIBUTE_SYSTEM | + FILE_ATTRIBUTE_HIDDEN; + unsigned info_level = SMB_FIND_FILE_BOTH_DIRECTORY_INFO; + struct tevent_req *req; + NTSTATUS status; + struct file_info *finfos; + size_t i, num_finfos; + PyObject *result; + + const char *kwlist[] = { + "mask", "attribute", "info_level", NULL + }; + + if (!ParseTupleAndKeywords( + args, kwds, "s|II", kwlist, + &mask, &attribute, &info_level)) { + return NULL; + } + + req = cli_list_send(NULL, self->ev, self->cli, mask, attribute, + info_level); -- Samba Shared Repository