diff --git a/src/backends/default/meson.build b/src/backends/default/meson.build index dddd176..4aba107 100644 --- a/src/backends/default/meson.build +++ b/src/backends/default/meson.build @@ -37,7 +37,8 @@ executable('thumb', [ executable('mv', [ '../../shared/sha.c', 'mv.c', - 'meta.c' + 'meta.c', + 'status.c' ], include_directories: inc, dependencies: deps, diff --git a/src/backends/default/mv.c b/src/backends/default/mv.c index ae40562..abc9873 100644 --- a/src/backends/default/mv.c +++ b/src/backends/default/mv.c @@ -13,17 +13,114 @@ #include "cmd.h" #include "eina_strbuf.h" +#include "eina_types.h" #include "sha.h" #include "meta.h" +#include "status.h" static const char *config_dir = NULL; +static Eina_Bool +fs_mv(const char *src, const char *dst, Eina_Bool report_err) +{ + // void status_begin(void); + // void status_end(void); + // void status_count(unsigned long long num_inc, const char *str); + // void status_pos(unsigned long long pos_inc, const char *str)); + // void status_error(const char *path, const char *str); + Eina_Bool res = EINA_TRUE; + int ret; + // XXX: write out status file and update it + // XXX: ecore_file_mv() ? <- look at it + // XXX: utime()/utimes() -> utimensat() + status_count(1, src); + ret = rename(src, dst); + if (ret == 0) return res; + else + { + switch (errno) + { + case EACCES: + case EPERM: // permission denied + if (report_err) status_error(src, dst, "Move - Permission denied"); + res = EINA_FALSE; + break; + case EBUSY: // file or dir is busy + if (report_err) status_error(src, dst, "Move - File busy"); + res = EINA_FALSE; + break; + case EDQUOT: // no quota left + if (report_err) status_error(src, dst, "Move - Over quota"); + res = EINA_FALSE; + break; + case EFAULT: // should not happen - but src or dst outside addr space + if (report_err) status_error(src, dst, "Move - Address fault"); + res = EINA_FALSE; + break; + case EINVAL: // moving into a sub path of itself - invalid + if (report_err) status_error(src, dst, "Move on top of itself"); + res = EINA_FALSE; + break; + case EISDIR: // moving file/dir into itself + if (report_err) status_error(src, dst, "Move - Destination is dir"); + res = EINA_FALSE; + break; + case ELOOP: // too many symlinks in a loop + if (report_err) status_error(src, dst, "Move - Too many symlinks"); + res = EINA_FALSE; + break; + case EMLINK: // max links exceeded + if (report_err) status_error(src, dst, "Move - Too many source links"); + res = EINA_FALSE; + break; + case ENAMETOOLONG: // path too long (src or dst) + if (report_err) status_error(src, dst, "Move - Path too long"); + res = EINA_FALSE; + break; + case ENOENT: // src or dst doesn't exist + if (report_err) status_error(src, dst, "Move - File does not exist"); + res = EINA_FALSE; + break; + case ENOMEM: // out of mem + if (report_err) status_error(src, dst, "Move - Out of memory"); + res = EINA_FALSE; + break; + case ENOSPC: // out of space on disk + if (report_err) status_error(src, dst, "Move - Disk full"); + res = EINA_FALSE; + break; + case ENOTDIR: // moving dir on top of file + if (report_err) status_error(src, dst, "Move - On top of itself"); + res = EINA_FALSE; + break; + case ENOTEMPTY: + case EEXIST: // dst is not an empty dir + if (report_err) status_error(src, dst, "Move - Destination not empty"); + res = EINA_FALSE; + break; + case EROFS: // read only disk + if (report_err) status_error(src, dst, "Move - Read only filesystem"); + res = EINA_FALSE; + break; + case EXDEV: // revert to cp + rm + // XXX: handle fallback to cp + rm + break; + default: // WAT??? + res = EINA_FALSE; + break; + } + } + status_pos(1, src); + return res; +} int main(int argc, char **argv) { - // mv [src] [dst] + // mv [src] [dst] if (report_error) status_error(src, dst, "Move - Too + // many symlinks"); + const char *src, *dst, *fname, *home_dir; Eina_Strbuf *buf = NULL; @@ -83,51 +180,8 @@ main(int argc, char **argv) eina_strbuf_append(buf, dst); eina_strbuf_append(buf, "/"); eina_strbuf_append(buf, fname); - // XXX: write out status file and update it - // XXX: ecore_file_mv() ? <- look at it - if (rename(src, eina_strbuf_string_get(buf)) == -1) - { - fprintf(stderr, "MV: %s\n", strerror(errno)); - switch (errno) - { - case EACCES: - case EPERM: // permission denied - break; - case EBUSY: // file or dir is busy - break; - case EDQUOT: // no quota left - break; - case EFAULT: // should not happen - but src or dst outside addr space - break; - case EINVAL: // moving into a sub path of itsefl - invalid - break; - case EISDIR: // moving file on top of dir - break; - case ELOOP: // too many symlinks in a loop - break; - case EMLINK: // max links exceeded - break; - case ENAMETOOLONG: // path too long (src or dst) - break; - case ENOENT: // src or dst doesn't exist - break; - case ENOMEM: // out of mem - break; - case ENOSPC: // out of space on disk - break; - case ENOTDIR: // moving dir on top of file - break; - case ENOTEMPTY: - case EEXIST: // dst is not an empty dir - break; - case EROFS: // read only disk - break; - case EXDEV: // revert t640k - default: // WAT??? - break; - } - } - else + status_begin(); + if (fs_mv(src, eina_strbuf_string_get(buf), EINA_TRUE)) { Eina_Bool src_can_write, dst_can_write; const char *dstfile; @@ -147,7 +201,7 @@ main(int argc, char **argv) if ((src_meta) && (dst_meta) && (meta_path_prepare(dstfile))) { // XXX: use mv() rename wrapper than will cp - rename(src_meta, dst_meta); + fs_mv(src_meta, dst_meta, EINA_FALSE); } free(src_meta); free(dst_meta); @@ -158,14 +212,14 @@ main(int argc, char **argv) if ((src_meta) && (dst_meta) && (meta_path_prepare(dstfile))) { // XXX: use mv() rename wrapper than will cp - rename(src_meta, dst_meta); + fs_mv(src_meta, dst_meta, EINA_FALSE); } free(src_meta); free(dst_meta); } err: if (buf) eina_strbuf_free(buf); - // XXX: delete status file + status_end(); meta_shutdown();