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 3519ab0f91340d741a033a9c51a86e5138e84d17
Author: Carsten Haitzler (Rasterman) <ras...@rasterman.com>
AuthorDate: Tue Apr 30 17:07:37 2024 +0100
cleaner code - move file cp to own func etc.
---
src/backends/default/fs.c | 292 ++++++++++++++++++++++++----------------------
1 file changed, 153 insertions(+), 139 deletions(-)
diff --git a/src/backends/default/fs.c b/src/backends/default/fs.c
index 403704c..06f6216 100644
--- a/src/backends/default/fs.c
+++ b/src/backends/default/fs.c
@@ -15,22 +15,30 @@
#include "status.h"
#include "fs.h"
-// generic error handler. special case handling all errnos for everything is
-// pretty insane - so handle non-errors in switches and otherwise pass to
-// this tio handle the reast in a generic way.
-static void
-_error_handle(const char *src, const char *dst, const char *op, int errno_in)
+static Eina_Strbuf *
+error_strbuf_new(const char *op)
{
Eina_Strbuf *buf = eina_strbuf_new();
if (!buf) abort();
eina_strbuf_append(buf, op);
eina_strbuf_append(buf, ": ");
-#define HNDL(_err, _str) \
- _err: \
- eina_strbuf_append(buf, _str); \
- status_error(src, dst, eina_strbuf_string_get(buf)); \
- break
+ return buf;
+}
+
+// generic error handler. special case handling all errnos for everything is
+// pretty insane - so handle non-errors in switches and otherwise pass to
+// this tio handle the reast in a generic way.
+static void
+_error_handle(const char *src, const char *dst, const char *op, int errno_in)
+{
+ Eina_Strbuf *buf = error_strbuf_new(op);
+
+#define HNDL(_err, _str) \
+_err: \
+ eina_strbuf_append(buf, _str); \
+ status_error(src, dst, eina_strbuf_string_get(buf)); \
+ break
switch (errno_in)
{
HNDL(case EACCES, "Access denied");
@@ -61,6 +69,120 @@ _error_handle(const char *src, const char *dst, const char *op, int errno_in)
eina_strbuf_free(buf);
}
+static void
+error_ok_pos(const char *src, const char *op, const char *str)
+{
+ Eina_Strbuf *buf = error_strbuf_new(op);
+
+ eina_strbuf_append(buf, str);
+ status_pos(1, eina_strbuf_string_get(buf));
+ eina_strbuf_free(buf);
+}
+
+static Eina_Bool
+fs_cp_file(const char *src, const char *dst, const char *op, struct stat src_st)
+{
+ // copy a normal file from src to dst - use optimized copy range if possible
+ // and fall abck to read + write into userspace buffer otherwise. use the
+ // struct stat mode passed in for created file. return true if fully
+ // successful or false otherwise
+ int fd_in, fd_ou;
+ void *old_copy_buf = NULL;
+ Eina_Bool res = EINA_TRUE;
+
+ fd_in = open(src, O_RDONLY);
+ fd_ou = open(dst, O_WRONLY | O_CREAT, src_st.st_mode);
+ if ((fd_in >= 0) && (fd_ou >= 0))
+ {
+ ssize_t size = 1 * 1024 * 1024; // 1mb default for copy range
+ ssize_t ret, ret2;
+ off_t off_in = 0, off_ou = 0;
+ Eina_Bool old_copy = EINA_FALSE;
+
+ for (;;)
+ {
+ if (old_copy)
+ {
+ if (!old_copy_buf)
+ {
+ size = 256 * 1024; // drop to 256k buffer for r+w
+ old_copy_buf = malloc(size);
+ if (!old_copy_buf)
+ {
+ res = EINA_FALSE;
+ goto err;
+ }
+ }
+again_read:
+ ret = read(fd_in, old_copy_buf, size);
+ if (ret < 0)
+ {
+ switch (errno)
+ {
+ case EAGAIN:
+ case EINTR:
+ goto again_read;
+ default:
+ _error_handle(src, NULL, op, errno);
+ res = EINA_FALSE;
+ goto err;
+ }
+ }
+ else
+ {
+ off_in += ret;
+again_write:
+ ret2 = write(fd_ou, old_copy_buf, ret);
+ if (ret2 < 0)
+ {
+ switch (errno)
+ {
+ case EAGAIN:
+ case EINTR:
+ goto again_write;
+ default:
+ _error_handle(NULL, dst, op, errno);
+ res = EINA_FALSE;
+ goto err;
+ }
+ }
+ else if (ret2 == ret)
+ {
+ off_ou += ret;
+ if (ret < size) break; // end of file
+ }
+ }
+ }
+ else
+ {
+ ret = copy_file_range(fd_in, &off_in, fd_ou, &off_ou, size, 0);
+ if (ret < 0)
+ {
+ switch (errno)
+ {
+ case EOPNOTSUPP:
+ case EXDEV:
+ // fall back to old read+write copy into userspace buf
+ old_copy = EINA_TRUE;
+ break;
+ default:
+ _error_handle(src, dst, op, errno);
+ res = EINA_FALSE;
+ goto err;
+ }
+ }
+ else if (ret < size) break; // end of file
+ }
+ }
+ }
+ else res = EINA_FALSE;
+err:
+ if (old_copy_buf) free(old_copy_buf);
+ if (fd_in >= 0) close(fd_in);
+ if (fd_ou >= 0) close(fd_ou);
+ return res;
+}
+
// this scans a tree to build a potential operation progress count. it may
// not be 100% right as the fs can change while the scan happens and after
// so any move that devolves into a cp + rm isn't going to be atomic and
@@ -94,10 +216,7 @@ fs_scan(const char *src)
{
EINA_ITERATOR_FOREACH(it, s)
{
- if (res)
- {
- if (!fs_scan(s)) res = EINA_FALSE;
- }
+ if ((res) && (!fs_scan(s))) res = EINA_FALSE;
eina_stringshare_del(s);
}
eina_iterator_free(it);
@@ -125,9 +244,8 @@ fs_cp_rm(const char *src, const char *dst, Eina_Bool report_err, Eina_Bool cp,
mode_t old_umask;
struct timeval times[2];
const char *op = "";
- Eina_Strbuf *sbuf = NULL;
- if (strlen(src) < 1) return EINA_FALSE;
+ if ((!src) || (!dst) || (strlen(src) < 1)) return EINA_FALSE;
// first count how much work needs doing
if (!fs_scan(src)) return EINA_FALSE;
@@ -142,11 +260,7 @@ fs_cp_rm(const char *src, const char *dst, Eina_Bool report_err, Eina_Bool cp,
switch (errno)
{
case ENOENT: // ignore this error - file removed during scan ?
- eina_strbuf_reset(sbuf);
- eina_strbuf_append(sbuf, op);
- eina_strbuf_append(sbuf, ": ");
- eina_strbuf_append(sbuf, "File vanished");
- status_pos(1, eina_strbuf_string_get(sbuf));
+ error_ok_pos(src, op, "File vanished");
goto err;
default:
_error_handle(src, dst, op, errno);
@@ -154,7 +268,6 @@ fs_cp_rm(const char *src, const char *dst, Eina_Bool report_err, Eina_Bool cp,
goto err;
}
}
- sbuf = eina_strbuf_new();
if (S_ISDIR(st.st_mode))
{ // it's a dir - scan this recursively
if (cp)
@@ -165,7 +278,7 @@ fs_cp_rm(const char *src, const char *dst, Eina_Bool report_err, Eina_Bool cp,
{
case EEXIST: // ignore - mv would mv over this anyway
break;
- default: // WAT
+ default:
_error_handle(NULL, dst, op, errno);
res = EINA_FALSE;
goto err;
@@ -175,15 +288,18 @@ fs_cp_rm(const char *src, const char *dst, Eina_Bool report_err, Eina_Bool cp,
it = eina_file_ls(src);
if (it)
{
+ Eina_Strbuf *buf = eina_strbuf_new();
+
+ if (!buf) abort();
EINA_ITERATOR_FOREACH(it, s)
{
- Eina_Strbuf *buf = eina_strbuf_new();
const char *fs = ecore_file_file_get(s);
if (buf)
{
if ((res) && (fs))
{
+ eina_strbuf_reset(buf);
eina_strbuf_append(buf, dst);
eina_strbuf_append(buf, "/");
eina_strbuf_append(buf, fs);
@@ -191,11 +307,11 @@ fs_cp_rm(const char *src, const char *dst, Eina_Bool report_err, Eina_Bool cp,
report_err, cp, rm))
res = EINA_FALSE;
}
- eina_strbuf_free(buf);
}
eina_stringshare_del(s);
}
eina_iterator_free(it);
+ eina_strbuf_free(buf);
}
}
else if (S_ISLNK(st.st_mode))
@@ -210,11 +326,7 @@ fs_cp_rm(const char *src, const char *dst, Eina_Bool report_err, Eina_Bool cp,
{
if (symlink(link, dst) < 0)
{ // soft error? e.g. mv on FAT fs? report but move on
- eina_strbuf_reset(sbuf);
- eina_strbuf_append(sbuf, op);
- eina_strbuf_append(sbuf, ": ");
- eina_strbuf_append(sbuf, "Error creating symlink");
- status_pos(1, eina_strbuf_string_get(sbuf));
+ error_ok_pos(dst, op, "Error creating symlink");
}
}
else if (lnsz < 0)
@@ -222,24 +334,16 @@ fs_cp_rm(const char *src, const char *dst, Eina_Bool report_err, Eina_Bool cp,
switch (errno)
{
case ENOENT: // ignore this error - file removed during scan ?
- eina_strbuf_reset(sbuf);
- eina_strbuf_append(sbuf, op);
- eina_strbuf_append(sbuf, ": ");
- eina_strbuf_append(sbuf, "File vanished");
- status_pos(1, eina_strbuf_string_get(sbuf));
+ error_ok_pos(src, op, "File vanished");
break;
default:
_error_handle(src, dst, op, errno);
return EINA_FALSE;
}
}
- else // 0 sized symlink ... WAT?
- {
- eina_strbuf_reset(sbuf);
- eina_strbuf_append(sbuf, op);
- eina_strbuf_append(sbuf, ": ");
- eina_strbuf_append(sbuf, "Zero sized symlink");
- status_error(src, NULL, eina_strbuf_string_get(sbuf));
+ else
+ { // 0 sized symlink ... WAT?
+ error_ok_pos(src, op, "Zero sized symlink");
}
}
}
@@ -255,8 +359,7 @@ fs_cp_rm(const char *src, const char *dst, Eina_Bool report_err, Eina_Bool cp,
else if (S_ISSOCK(st.st_mode))
{
if (cp)
- {
- // we can't just make sockets - so ignore but document here
+ { // we can't just make sockets - so ignore but document here
}
}
else if ((S_ISCHR(st.st_mode)) || (S_ISBLK(st.st_mode)))
@@ -272,99 +375,7 @@ fs_cp_rm(const char *src, const char *dst, Eina_Bool report_err, Eina_Bool cp,
{
if (cp)
{
- int fd_in, fd_ou;
- void *old_copy_buf = NULL;
-
- fd_in = open(src, O_RDONLY);
- fd_ou = open(dst, O_WRONLY | O_CREAT, st.st_mode);
- if ((fd_in >= 0) && (fd_ou >= 0))
- {
- ssize_t size = 1 * 1024 * 1024; // 1mb default
- ssize_t ret, ret2;
- off_t off_in = 0, off_ou = 0;
- Eina_Bool old_copy = EINA_FALSE;
-
- for (;;)
- {
- if (old_copy)
- {
- if (!old_copy_buf)
- {
- size = 256 * 1024; // drop to 256k buffer
- old_copy_buf = malloc(size);
- if (!old_copy_buf)
- {
- res = EINA_FALSE;
- goto err_copy;
- }
- }
-again_read:
- ret = read(fd_in, old_copy_buf, size);
- if (ret < 0)
- {
- switch (errno)
- {
- case EAGAIN:
- case EINTR:
- goto again_read;
- default:
- _error_handle(src, NULL, op, errno);
- res = EINA_FALSE;
- goto err_copy;
- }
- }
- else
- {
- off_in += ret;
-again_write:
- ret2 = write(fd_ou, old_copy_buf, ret);
- if (ret2 < 0)
- {
- switch (errno)
- {
- case EAGAIN:
- case EINTR:
- goto again_write;
- default:
- _error_handle(NULL, dst, op, errno);
- res = EINA_FALSE;
- goto err_copy;
- }
- }
- else if (ret2 == ret)
- {
- off_ou += ret;
- if (ret < size) break; // end of file
- }
- }
- }
- else
- {
- ret = copy_file_range(fd_in, &off_in, fd_ou, &off_ou,
- size, 0);
- if (ret < 0)
- {
- switch (errno)
- {
- case EOPNOTSUPP:
- case EXDEV:
- old_copy = EINA_TRUE;
- break;
- case EBADF:
- default: // WAT
- _error_handle(src, dst, op, errno);
- res = EINA_FALSE;
- goto err_copy;
- }
- }
- else if (ret < size) break; // end of file
- }
- }
- }
-err_copy:
- if (old_copy_buf) free(old_copy_buf);
- if (fd_in >= 0) close(fd_in);
- if (fd_ou >= 0) close(fd_ou);
+ res = fs_cp_file(src, dst, op, st);
}
}
if ((rm) && (res))
@@ -380,9 +391,12 @@ err_copy:
default:
_error_handle(src, NULL, op, errno);
res = EINA_FALSE;
- goto err;
+ goto err_unlink;
}
}
+ }
+ else
+ {
if (unlink(src) != 0)
{
switch (errno)
@@ -399,6 +413,7 @@ err_copy:
}
err_unlink:
chown(dst, st.st_uid, st.st_gid); // ignore err
+// duplicate mtime+atime from src down to msic/nsec if possible
#ifdef STAT_NSEC
#ifdef st_mtime
#define STAT_NSEC_ATIME(st) (unsigned long long)((st)->st_atim.tv_nsec)
@@ -421,7 +436,6 @@ err_unlink:
utimes(dst, times); // ingore err
err:
umask(old_umask);
- if (sbuf) eina_strbuf_free(sbuf);
return res;
}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.