From 4851309c8b0b83e657a1b63a6bc2ac630ebffc2c Mon Sep 17 00:00:00 2001 From: Nicholas Hughart Date: Tue, 2 Sep 2008 02:44:47 +0000 Subject: [PATCH] Another update to ecore_file_mv to make it work even better. Now even writes to external devices will be atomic if possible. If it's still not possible, the old fallback method of just copying will be done. SVN revision: 35787 --- legacy/ecore/src/lib/ecore_file/ecore_file.c | 52 ++++++++++++++++++-- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/legacy/ecore/src/lib/ecore_file/ecore_file.c b/legacy/ecore/src/lib/ecore_file/ecore_file.c index 1e828385a0..ecb7b515f0 100644 --- a/legacy/ecore/src/lib/ecore_file/ecore_file.c +++ b/legacy/ecore/src/lib/ecore_file/ecore_file.c @@ -295,24 +295,66 @@ ecore_file_cp(const char *src, const char *dst) EAPI int ecore_file_mv(const char *src, const char *dst) { + char buf[PATH_MAX]; + int fd; + if (rename(src, dst)) { + // File cannot be moved directly because + // it resides on a different mount point. if (errno == EXDEV) { struct stat st; + // Make sure this is a regular file before + // we do anything fancy. stat(src, &st); if (S_ISREG(st.st_mode)) { - ecore_file_cp(src, dst); - chmod(dst, st.st_mode); - ecore_file_unlink(src); - return 1; + // Since we can't directly rename, try to + // copy to temp file in the dst directory + // and then rename. + snprintf(buf, sizeof(buf), "%s/.%s.tmp.XXXXXX", + ecore_file_dir_get(dst), + ecore_file_file_get(dst)); + fd = mkstemp(buf); + if(fd < 0) + { + perror("mkstemp"); + goto FAIL; + } + close(fd); + + // Copy to temp file + if(!ecore_file_cp(src,buf)) + goto FAIL; + + // Set file permissions of temp file to match src + chmod(buf, st.st_mode); + + // Try to atomically move temp file to dst + if (rename(buf, dst)) + { + // If we still cannot atomically move + // do a normal copy and hope for the best. + if(!ecore_file_cp(buf, dst)) + goto FAIL; + } + + // Delete temporary file and src + ecore_file_unlink(buf); + ecore_file_unlink(src); + goto PASS; } } - return 0; + goto FAIL; } + + PASS: return 1; + + FAIL: + return 0; } /**