s3:pylibsmb: Add .unlink() API to SMB Py bindings
authorTim Beale <timbeale@catalyst.net.nz>
Sun, 2 Dec 2018 21:50:19 +0000 (10:50 +1300)
committerTim Beale <timbeale@samba.org>
Mon, 7 Jan 2019 00:23:07 +0000 (01:23 +0100)
Add a basic .unlink() API to the source3 bindings. This is based on the
source4 python bindings, but uses the source3 client library APIs.
(We use a helper function to do most of the work, because we will need
to reuse it in order to support the deltree API).

Update the source4 test to use the source3 API. We will gradually
convert it over, and then delete the source4 python bindings.

Pair-Programmed-With: Stefan Metzmacher <metze@samba.org>

BUG: https://bugzilla.samba.org/show_bug.cgi?id=13676

Signed-off-by: Tim Beale <timbeale@catalyst.net.nz>
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
python/samba/tests/smb.py
source3/libsmb/pylibsmb.c

index 6893647..a74db3b 100644 (file)
@@ -23,6 +23,8 @@ from samba import smb
 from samba import NTSTATUSError
 from samba.ntstatus import (NT_STATUS_OBJECT_NAME_NOT_FOUND,
                             NT_STATUS_OBJECT_PATH_NOT_FOUND)
+from samba.samba3 import libsmb_samba_internal
+from samba.samba3 import param as s3param
 
 PY3 = sys.version_info[0] == 3
 addom = 'addom.samba.example.com/'
@@ -44,6 +46,13 @@ class SMBTests(samba.tests.TestCase):
                             "sysvol",
                             lp=self.get_loadparm(),
                             creds=creds)
+
+        # temporarily create a 2nd SMB connection for migrating the py-bindings
+        lp = s3param.get_context()
+        lp.load(os.getenv("SMB_CONF_PATH"))
+        self.smb_conn = libsmb_samba_internal.Conn(self.server, "sysvol",
+                                                   lp, creds)
+
         self.conn.mkdir(test_dir)
 
     def tearDown(self):
@@ -161,7 +170,7 @@ class SMBTests(samba.tests.TestCase):
         self.assertTrue(self.file_exists(test_file))
 
         # delete it and check that it's gone
-        self.conn.unlink(test_file)
+        self.smb_conn.unlink(test_file)
         self.assertFalse(self.file_exists(test_file))
 
     def test_chkpath(self):
index c1be26b..ab7400a 100644 (file)
@@ -965,6 +965,46 @@ static PyObject *py_cli_list(struct py_cli_state *self,
        return result;
 }
 
+/*
+ * Deletes a file
+ */
+static NTSTATUS unlink_file(struct py_cli_state *self, const char *filename)
+{
+       NTSTATUS status;
+       uint16_t attrs = (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
+
+       if (self->is_smb1) {
+               struct tevent_req *req = NULL;
+
+               req = cli_unlink_send(NULL, self->ev, self->cli, filename,
+                                     attrs);
+               if (!py_tevent_req_wait_exc(self, req)) {
+                       return NT_STATUS_INTERNAL_ERROR;
+               }
+               status = cli_unlink_recv(req);
+               TALLOC_FREE(req);
+       } else {
+               status = cli_unlink(self->cli, filename, attrs);
+       }
+
+       return status;
+}
+
+static PyObject *py_smb_unlink(struct py_cli_state *self, PyObject *args)
+{
+       NTSTATUS status;
+       const char *filename = NULL;
+
+       if (!PyArg_ParseTuple(args, "s:unlink", &filename)) {
+               return NULL;
+       }
+
+       status = unlink_file(self, filename);
+       PyErr_NTSTATUS_NOT_OK_RAISE(status);
+
+       Py_RETURN_NONE;
+}
+
 static PyMethodDef py_cli_state_methods[] = {
        { "settimeout", (PyCFunction)py_cli_settimeout, METH_VARARGS,
          "settimeout(new_timeout_msecs) => return old_timeout_msecs" },
@@ -987,6 +1027,9 @@ static PyMethodDef py_cli_state_methods[] = {
          "List a directory" },
        { "get_oplock_break", (PyCFunction)py_cli_get_oplock_break,
          METH_VARARGS, "Wait for an oplock break" },
+       { "unlink", (PyCFunction)py_smb_unlink,
+         METH_VARARGS,
+         "unlink(path) -> None\n\n \t\tDelete a file." },
        { NULL, NULL, 0, NULL }
 };