pylibsmb: Move deltree to python code
authorVolker Lendecke <vl@samba.org>
Fri, 6 Nov 2020 21:08:00 +0000 (22:08 +0100)
committerJeremy Allison <jra@samba.org>
Mon, 16 Nov 2020 19:53:44 +0000 (19:53 +0000)
This is much shorter. There's also another aspect: I'm working on
improving cli_list() to not collect all files before starting to call
the callback function. This means that the cli_list cb will be called
from within tevent_loop_once(). In pylibsmb.c's deltree code this
would create a nested event loop. By moving the deltree code into the
python world this nested event loop is avoided. Now the python code
will first collect everything and then start to delete, avoiding the
nesting. A future development should make listing directories a
generator or something like that.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
python/samba/samba3/libsmb_samba_internal.py
source3/libsmb/pylibsmb.c

index d8621a270a6ead2c4571207930e959185f5d6eb8..d0d611fbc5dcb3f26ac5d79ccf9ceb837de07b52 100644 (file)
 from samba.samba3.libsmb_samba_cwrapper import *
 
 class Conn(LibsmbCConn):
-    pass
+    def deltree(self, path):
+        if self.chkpath(path):
+            for entry in self.list(path):
+                self.deltree(path + "\\" + entry['name'])
+            self.rmdir(path)
+        else:
+            self.unlink(path)
index 78bc066ba4f76dca5ccb007a1e0fdbce94a677e1..471f21d0a69a1a12094f7b0678f52c761ac7894e 100644 (file)
@@ -1361,97 +1361,6 @@ static PyObject *py_smb_chkpath(struct py_cli_state *self, PyObject *args)
        return PyBool_FromLong(dir_exists);
 }
 
-struct deltree_state {
-       struct py_cli_state *self;
-       const char *full_dirpath;
-};
-
-static NTSTATUS delete_dir_tree(struct py_cli_state *self,
-                               const char *dirpath);
-
-/*
- * Deletes a single item in the directory tree. This could be either a file
- * or a directory. This function gets invoked as a callback for every item in
- * the given directory's listings.
- */
-static NTSTATUS delete_tree_callback(struct file_info *finfo,
-                                    const char *mask, void *priv)
-{
-       char *filepath = NULL;
-       struct deltree_state *state = priv;
-       NTSTATUS status;
-
-       /* skip '.' or '..' directory listings */
-       if (ISDOT(finfo->name) || ISDOTDOT(finfo->name)) {
-               return NT_STATUS_OK;
-       }
-
-       /* get the absolute filepath */
-       filepath = talloc_asprintf(NULL, "%s\\%s", state->full_dirpath,
-                                  finfo->name);
-       if (filepath == NULL) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       if (finfo->attr & FILE_ATTRIBUTE_DIRECTORY) {
-
-               /* recursively delete the sub-directory and its contents */
-               status = delete_dir_tree(state->self, filepath);
-       } else {
-               status = unlink_file(state->self, filepath);
-       }
-
-       TALLOC_FREE(filepath);
-       return status;
-}
-
-/*
- * Removes a directory and all its contents
- */
-static NTSTATUS delete_dir_tree(struct py_cli_state *self,
-                               const char *filepath)
-{
-       NTSTATUS status;
-       const char *mask = "*";
-       struct deltree_state state = { 0 };
-
-       /* go through the directory's contents, deleting each item */
-       state.self = self;
-       state.full_dirpath = filepath;
-       status = do_listing(self, filepath, mask, LIST_ATTRIBUTE_MASK,
-                           delete_tree_callback, &state);
-
-       /* remove the directory itself */
-       if (NT_STATUS_IS_OK(status)) {
-               status = remove_dir(self, filepath);
-       }
-       return status;
-}
-
-static PyObject *py_smb_deltree(struct py_cli_state *self, PyObject *args)
-{
-       NTSTATUS status;
-       const char *filepath = NULL;
-       bool dir_exists;
-
-       if (!PyArg_ParseTuple(args, "s:deltree", &filepath)) {
-               return NULL;
-       }
-
-       /* check whether we're removing a directory or a file */
-       dir_exists = check_dir_path(self, filepath);
-
-       if (dir_exists) {
-               status = delete_dir_tree(self, filepath);
-       } else {
-               status = unlink_file(self, filepath);
-       }
-
-       PyErr_NTSTATUS_IS_ERR_RAISE(status);
-
-       Py_RETURN_NONE;
-}
-
 /*
  * Read ACL on a given file/directory as a security descriptor object
  */
@@ -1596,9 +1505,6 @@ static PyMethodDef py_cli_state_methods[] = {
        { "loadfile", (PyCFunction)py_smb_loadfile, METH_VARARGS,
          "loadfile(path) -> file contents as a " PY_DESC_PY3_BYTES
          "\n\n\t\tRead contents of a file." },
-       { "deltree", (PyCFunction)py_smb_deltree, METH_VARARGS,
-         "deltree(path) -> None\n\n"
-         "\t\tDelete a directory and all its contents." },
        { "get_acl", (PyCFunction)py_smb_getacl, METH_VARARGS,
          "get_acl(path[, security_info=0]) -> security_descriptor object\n\n"
          "\t\tGet security descriptor for file." },