This is an automated email from the git hooks/post-receive script.

git pushed a commit to branch master
in repository efm2.

View the commit online.

commit 3e70c488c48a8f48ee55b7cf687ebde681377843
Author: Carsten Haitzler (Rasterman) <ras...@rasterman.com>
AuthorDate: Tue May 21 17:41:39 2024 +0100

    move file list to stdin to fs op cmd
---
 src/backends/default/fs.c        |  13 ++--
 src/backends/default/fs.h        |   8 +--
 src/backends/default/meson.build |   2 +
 src/backends/default/mv.c        | 141 ++++++++++++++++++++++++++++-----------
 src/backends/default/open.c      |  71 ++++++++++++++------
 src/backends/default/status.c    |   2 +
 src/shared/esc.c                 |  66 ++++++++++++++++++
 src/shared/esc.h                 |   7 ++
 8 files changed, 239 insertions(+), 71 deletions(-)

diff --git a/src/backends/default/fs.c b/src/backends/default/fs.c
index 06f6216..491037e 100644
--- a/src/backends/default/fs.c
+++ b/src/backends/default/fs.c
@@ -70,7 +70,7 @@ _err:                                                  \
 }
 
 static void
-error_ok_pos(const char *src, const char *op, const char *str)
+error_ok_pos(const char *src EINA_UNUSED, const char *op, const char *str)
 {
   Eina_Strbuf *buf = error_strbuf_new(op);
 
@@ -247,12 +247,9 @@ fs_cp_rm(const char *src, const char *dst, Eina_Bool report_err, Eina_Bool cp,
 
   if ((!src) || (!dst) || (strlen(src) < 1)) return EINA_FALSE;
 
-  // first count how much work needs doing
-  if (!fs_scan(src)) return EINA_FALSE;
-
-  if (rm && cp) op = "Move";
-  else if (!rm && cp) op = "Copy";
-  else if (rm && !cp) op = "Delete";
+  if      ( rm &&  cp) op = "Move";
+  else if (!rm &&  cp) op = "Copy";
+  else if ( rm && !cp) op = "Delete";
 
   old_umask = umask(0);
   if (lstat(src, &st) != 0)
@@ -466,3 +463,5 @@ fs_mv(const char *src, const char *dst, Eina_Bool report_err)
   status_pos(1, src);
   return res;
 }
+
+// add fs_cp() fs_rm() fs_trash() fs_rename()
\ No newline at end of file
diff --git a/src/backends/default/fs.h b/src/backends/default/fs.h
index cb50630..c60b212 100644
--- a/src/backends/default/fs.h
+++ b/src/backends/default/fs.h
@@ -2,9 +2,9 @@
 #define FS_H
 #include <Eina.h>
 
-Eina_Bool fs_scan(const char *src);
-Eina_Bool fs_cp_rm(const char *src, const char *dst, Eina_Bool report_err,
-                   Eina_Bool cp, Eina_Bool rm);
-Eina_Bool fs_mv(const char *src, const char *dst, Eina_Bool report_err);
+Eina_Bool  fs_scan(const char *src);
+Eina_Bool  fs_cp_rm(const char *src, const char *dst, Eina_Bool report_err,
+                    Eina_Bool cp, Eina_Bool rm);
+Eina_Bool  fs_mv(const char *src, const char *dst, Eina_Bool report_err);
 
 #endif
\ No newline at end of file
diff --git a/src/backends/default/meson.build b/src/backends/default/meson.build
index c464309..b2f1749 100644
--- a/src/backends/default/meson.build
+++ b/src/backends/default/meson.build
@@ -9,6 +9,7 @@ inc = include_directories(
 executable('open', [
     '../../shared/cmd.c',
     '../../shared/sha.c',
+    '../../shared/esc.c',
     '../../backends/common/fs_backend_core.c',
     'open.c',
     'meta.c'
@@ -36,6 +37,7 @@ executable('thumb', [
   install_dir: dir)
 executable('mv', [
     '../../shared/sha.c',
+    '../../shared/esc.c',
     'fs.c',
     'mv.c',
     'meta.c',
diff --git a/src/backends/default/mv.c b/src/backends/default/mv.c
index 3cfe971..73b4b0c 100644
--- a/src/backends/default/mv.c
+++ b/src/backends/default/mv.c
@@ -14,23 +14,76 @@
 #include "meta.h"
 #include "status.h"
 #include "fs.h"
+#include "esc.h"
 
 static const char *config_dir = NULL;
 
+typedef struct _File_Set
+{
+  const char *src, *dst;
+} File_Set;
+
+static void
+mem_abort(void)
+{
+  fprintf(stderr, "Out of memory!\n");
+  abort();
+}
+
+static Eina_List *
+file_set_add(Eina_List *files, const char *src, const char *dst)
+{
+  File_Set *fs = calloc(1, sizeof(File_Set));
+  if (!fs) mem_abort();
+  fs->src = ""
+  fs->dst = eina_stringshare_add(dst);
+  if ((!fs->src) || (!fs->dst)) mem_abort();
+  files   = eina_list_append(files, fs);
+  return files;
+}
+
 int
 main(int argc, char **argv)
-{ // mv [src] [dst]
-  const char *src, *dst, *fname, *home_dir;
+{ // mv [src] [dstdir]
+  const char  *fname, *home_dir;
   Eina_Strbuf *buf = NULL;
+  Eina_List   *files = NULL, *l;
+  File_Set    *fs;
+  size_t       sz;
+  char        *src = "" *dst = NULL;
+  char         sbuf[4096 + 256];
 
-  if (argc < 3) return -1;
-  src = ""
-  dst = argv[2];
   eina_init();
   eet_init();
   ecore_init();
   efreet_init();
 
+  for (;;)
+    { // read stdin of key=val\n ... or end\n
+      if (!fgets(sbuf, sizeof(sbuf), stdin)) break;
+      sz = strlen(sbuf);
+      if (sz < 1) break; // too small
+      if (sbuf[sz - 1] == '\n') sbuf[sz - 1] = '\0'; // remove \n if there
+      if (!strncmp(sbuf, "src="" 4))
+        {
+          if (src) free(src);
+          src = "" + 4);
+        }
+      else if (!strncmp(sbuf, "dst=", 4))
+        {
+          if (dst) free(dst);
+          dst = unescape(sbuf + 4);
+          if ((src) && (dst)) files = file_set_add(files, src, dst);
+          if (src) free(src);
+          if (dst) free(dst);
+          src = ""
+          dst = NULL;
+        }
+      else if (!strcmp(sbuf, "end")) break;
+    }
+  if (src) free(src);
+  if (dst) free(dst);
+
   config_dir = getenv("E_HOME_DIR");
   home_dir   = getenv("HOME");
   if (!home_dir) return 77; // no $HOME? definitely an error!
@@ -43,47 +96,59 @@ main(int argc, char **argv)
     }
   meta_init(config_dir);
 
-  fname = ecore_file_file_get(src);
-  if (!fname) goto err;
   buf = eina_strbuf_new();
   if (!buf) goto err;
-  eina_strbuf_append(buf, dst);
-  eina_strbuf_append(buf, "/");
-  eina_strbuf_append(buf, fname);
+
   status_begin();
-  if (fs_mv(src, eina_strbuf_string_get(buf), EINA_TRUE))
-    {
-      Eina_Bool src_can_write, dst_can_write;
-      const char *dstfile;
-      char *src_meta, *dst_meta;
+  EINA_LIST_FOREACH(files, l, fs)
+  {
+    if (strlen(fs->src) < 1) goto err2;
+    if (!fs_scan(fs->src)) goto err2;
+  }
 
-      dstfile = eina_strbuf_string_get(buf);
-      
-      src_can_write = meta_path_can_write(src);
-      dst_can_write = meta_path_can_write(eina_strbuf_string_get(buf));
+  EINA_LIST_FOREACH(files, l, fs)
+  {
+    fname = ecore_file_file_get(fs->src);
+    if (!fname) break;
+    eina_strbuf_reset(buf);
+    eina_strbuf_append(buf, fs->dst);
+    eina_strbuf_append(buf, "/");
+    eina_strbuf_append(buf, fname);
+    if (fs_mv(fs->src, eina_strbuf_string_get(buf), EINA_TRUE))
+      {
+        Eina_Bool   src_can_write, dst_can_write;
+        const char *dstfile;
+        char       *src_meta, *dst_meta;
 
-      if (src_can_write) src_meta = meta_path_find(src, "meta.efm");
-      else src_meta = meta_path_user_find(src, "meta.efm");
-      if (dst_can_write) dst_meta = meta_path_find(dstfile, "meta.efm");
-      else dst_meta = meta_path_user_find(dstfile, "meta.efm");
-      if ((src_meta) && (dst_meta) && (meta_path_prepare(dstfile)))
-        fs_mv(src_meta, dst_meta, EINA_FALSE);
-      free(src_meta);
-      free(dst_meta);
-      if (src_can_write) src_meta = meta_path_find(src, "thumb.efm");
-      else src_meta = meta_path_user_find(src, "thumb.efm");
-      if (dst_can_write) dst_meta = meta_path_find(dstfile, "thumb.efm");
-      else dst_meta = meta_path_user_find(dstfile, "thumb.efm");
-      if ((src_meta) && (dst_meta) && (meta_path_prepare(dstfile)))
-        fs_mv(src_meta, dst_meta, EINA_FALSE);
-      free(src_meta);
-      free(dst_meta);
-    }
-  else status_end();
+        dstfile = eina_strbuf_string_get(buf);
+
+        src_can_write = meta_path_can_write(fs->src);
+        dst_can_write = meta_path_can_write(eina_strbuf_string_get(buf));
+
+        if (src_can_write) src_meta = meta_path_find(fs->src, "meta.efm");
+        else src_meta = meta_path_user_find(fs->src, "meta.efm");
+        if (dst_can_write) dst_meta = meta_path_find(dstfile, "meta.efm");
+        else dst_meta = meta_path_user_find(dstfile, "meta.efm");
+        if ((src_meta) && (dst_meta) && (meta_path_prepare(dstfile)))
+          fs_mv(src_meta, dst_meta, EINA_FALSE);
+        free(src_meta);
+        free(dst_meta);
+        if (src_can_write) src_meta = meta_path_find(fs->src, "thumb.efm");
+        else src_meta = meta_path_user_find(fs->src, "thumb.efm");
+        if (dst_can_write) dst_meta = meta_path_find(dstfile, "thumb.efm");
+        else dst_meta = meta_path_user_find(dstfile, "thumb.efm");
+        if ((src_meta) && (dst_meta) && (meta_path_prepare(dstfile)))
+          fs_mv(src_meta, dst_meta, EINA_FALSE);
+        free(src_meta);
+        free(dst_meta);
+      }
+    else break;
+  }
+err2:
+  status_end();
 
 err:
   if (buf) eina_strbuf_free(buf);
-  status_end();
 
   meta_shutdown();
 
diff --git a/src/backends/default/open.c b/src/backends/default/open.c
index 6e97f87..0ea4de8 100644
--- a/src/backends/default/open.c
+++ b/src/backends/default/open.c
@@ -21,6 +21,7 @@
 #include "sha.h"
 #include "meta.h"
 #include "thumb_check.h"
+#include "esc.h"
 
 static const char *icon_theme = NULL;
 static const char *config_dir = NULL;
@@ -1233,33 +1234,48 @@ _path_in_mon_dir(const char *path)
 }
 
 static void
-_op_run(const char *op, const char *src, const char *dst)
+_op_run(const char *op, Eina_List *files, const char *dst)
 {
   Eina_Strbuf *buf;
   const char  *s;
+  char        *str;
+  Eina_List   *l;
+  Ecore_Exe   *exe;
 
-  buf       = eina_strbuf_new();
-  s         = getenv("EFM_BACKEND_DIR");
+  buf = eina_strbuf_new();
+  s   = getenv("EFM_BACKEND_DIR");
   if (!s) return;
   eina_strbuf_append(buf, s);
   eina_strbuf_append(buf, "/");
   eina_strbuf_append(buf, op);
-  eina_strbuf_append(buf, " ");
-  _strbuf_append_file_escaped(buf, src);
-  if (dst)
-    {
-      eina_strbuf_append(buf, " ");
-      _strbuf_append_file_escaped(buf, dst);
-    }
-  fprintf(stderr, "OP: [%s]\n", eina_strbuf_string_get(buf));
-  ecore_exe_run(eina_strbuf_string_get(buf), NULL);
+  fprintf(stderr, "OP: op [%s]\n", eina_strbuf_string_get(buf));
+  exe = ecore_exe_pipe_run(eina_strbuf_string_get(buf), ECORE_EXE_PIPE_WRITE,
+                           NULL);
+  eina_strbuf_reset(buf);
+  EINA_LIST_FOREACH(files, l, s)
+  {
+    fprintf(stderr, "OP [%s] -> [%s]\n", s, dst);
+    eina_strbuf_append(buf, "src=""
+    str = escape(s);
+    eina_strbuf_append(buf, str);
+    free(str);
+    eina_strbuf_append(buf, "\ndst=");
+    str = escape(dst);
+    eina_strbuf_append(buf, str);
+    free(str);
+    eina_strbuf_append(buf, "\n");
+  }
+  eina_strbuf_append(buf, "end\n");
+  ecore_exe_send(exe, eina_strbuf_string_get(buf), eina_strbuf_length_get(buf));
   eina_strbuf_free(buf);
 }
 
 static void
-_handle_drop_paste(const char *over, const char *action, const char *path)
+_handle_drop_paste(const char *over, const char *action, Eina_List *files)
 {
+  const char *path;
   const char *mondir;
+  Eina_List  *l;
 
   if (!mon) return;
   mondir = ecore_file_monitor_path_get(mon);
@@ -1268,26 +1284,29 @@ _handle_drop_paste(const char *over, const char *action, const char *path)
     { // if you are dropping over a dir then spin up a sub open and pass
       // the dnd to it
       Eina_Strbuf *strbuf;
-      Sub *sub;
+      Sub         *sub;
 
       sub = _sub_find(over);
       if (!sub) sub = _sub_open(over, "default");
       strbuf = cmd_strbuf_new("dnd-drop");
       cmd_strbuf_append(strbuf, "action", action);
-      cmd_strbuf_append(strbuf, "path", path);
+      EINA_LIST_FOREACH(files, l, path)
+      {
+        fprintf(stderr, "DROP in [%s] over=[%s] action=""  >  [%s]\n", mondir,
+                over, action, path);
+        cmd_strbuf_append(strbuf, "path", path);
+      }
       _sub_cmd_send(sub, strbuf);
-      fprintf(stderr, "DROP in [%s] over=[%s] action=""  >  [%s]\n",
-              mondir, over, action, path);
     }
   else
     {
-      fprintf(stderr, "DROP in [%s] action=""  >  [%s]\n", mondir, action,
-              path);
       if ((!action) || (!strcmp(action, "copy")))
         { // XXX: implement
         }
       else if (!strcmp(action, "move"))
-        _op_run("mv", path, mondir);
+        {
+          _op_run("mv", files, mondir);
+        }
       else if (!strcmp(action, "ask"))
         { // XXX: implement
         }
@@ -1409,6 +1428,8 @@ do_handle_cmd(Cmd *c)
     { // "over" key means dnd was on that dir
       const char *over = cmd_key_find(c, "over");
       const char *action = "" "action");
+      Eina_List *files = NULL;
+      const char *s;
 
       KEY_WALK_BEGIN
       {
@@ -1417,12 +1438,18 @@ do_handle_cmd(Cmd *c)
             if (!over)
               {
                 if (!_path_in_mon_dir(data))
-                  _handle_drop_paste(over, action, data);
+                  files = eina_list_append(files, eina_stringshare_add(data));
               }
-            else _handle_drop_paste(over, action, data);
+            else
+              files = eina_list_append(files, eina_stringshare_add(data));
           }
         }
       KEY_WALK_END
+      if (files)
+        {
+          _handle_drop_paste(over, action, files);
+          EINA_LIST_FREE(files, s) eina_stringshare_del(s);
+        }
     }
   else if (!strcmp(c->command, "cnp-paste"))
     { // XXX: implement
diff --git a/src/backends/default/status.c b/src/backends/default/status.c
index 973e275..8501e39 100644
--- a/src/backends/default/status.c
+++ b/src/backends/default/status.c
@@ -2,7 +2,9 @@
 #define EFL_BETA_API_SUPPORT 1
 // for vasprintf()
 #define _GNU_SOURCE
+
 #include "status.h"
+
 #include <Eina.h>
 #include <Ecore_File.h>
 #include <fcntl.h>
diff --git a/src/shared/esc.c b/src/shared/esc.c
new file mode 100644
index 0000000..27a8493
--- /dev/null
+++ b/src/shared/esc.c
@@ -0,0 +1,66 @@
+#include <Eina.h>
+#include <ctype.h>
+
+#include "esc.h"
+
+
+static inline int
+_xtov(char x)
+{
+  if ((x >= '0') && (x <= '9')) return x - '0';
+  if ((x >= 'a') && (x <= 'f')) return 10 + (x - 'a');
+  if ((x >= 'A') && (x <= 'F')) return 10 + (x - 'A');
+  return 0;
+}
+
+char *
+escape(const char *src_in)
+{
+  Eina_Strbuf *strbuf = eina_strbuf_new();
+  char        *str;
+  const char  *s;
+
+  for (s = src_in; *s; s++)
+    {
+      if ((*s <= ',') || (*s == '%') || ((*s >= ':') && (*s <= '@'))
+          || ((*s >= '[') && (*s <= '`')) || (*s >= '{'))
+        {
+          unsigned char tmp;
+
+          tmp = s[0];
+          eina_strbuf_append_printf(strbuf, "%%%02x", tmp);
+        }
+      else eina_strbuf_append_char(strbuf, *s);
+    }
+  str = eina_strbuf_string_steal(strbuf);
+  eina_strbuf_free(strbuf);
+  return str;
+}
+
+char *
+unescape(const char *src_in)
+{
+  char       *dest = malloc(strlen(src_in) + 1);
+  char       *d;
+  const char *s;
+
+  for (d = dest, s = src_in; *s; d++)
+    {
+      if ((s[0] == '%') && (!isspace(s[1])))
+        {
+          if ((s[1]) && (s[2]))
+            {
+              *d = (_xtov(s[1]) << 4) | (_xtov(s[2]));
+              s += 3;
+            }
+          else s++;
+        }
+      else
+        {
+          *d = s[0];
+          s++;
+        }
+    }
+  *d = 0;
+  return dest;
+}
\ No newline at end of file
diff --git a/src/shared/esc.h b/src/shared/esc.h
new file mode 100644
index 0000000..a2effe7
--- /dev/null
+++ b/src/shared/esc.h
@@ -0,0 +1,7 @@
+#ifndef ESC_H
+#define ESC_H 1
+
+char *escape(const char *src_in);
+char *unescape(const char *src_in);
+
+#endif
\ No newline at end of file

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.

Reply via email to