const std::function<void(FilesystemError)>& error_cb) {
LoggerD("enter");
+
int status = rename(oldPath.c_str(), newPath.c_str());
- if (0 == status) {
- FilesystemStat fileStat = FilesystemStat::getStat(newPath);
- if (fileStat.valid) {
- success_cb(FilesystemStat::getStat(newPath));
- } else {
- LoggerE("Cannot perform stat on new path!");
+ if (0 != status) {
+ if(EXDEV != errno) {
+ LoggerE("Error while moving file");
error_cb(FilesystemError::Other);
+ return;
+ }
+
+ LoggerD("Files are not on the same mounted file system");
+ //In case of EXDEV we need to copy and remove file
+ //EXDEV - oldpath and newpath are not on the same mounted file system.
+ //Linux permits a file system to be mounted at multiple points, but rename() does not work
+ //across different mount points, even if the same file system is mounted on both.
+
+ if (FilesystemError::None != copyFile(oldPath, newPath)) {
+ LoggerE("Error while copying file");
+ error_cb(FilesystemError::Other);
+ return;
+ }
+
+ struct stat fileStat;
+ if (0 != stat(oldPath.c_str(), &fileStat)) {
+ LoggerE("Error while getting file status [%s]", GetErrorString(errno).c_str());
+ error_cb(FilesystemError::Other);
+ return;
+ }
+
+ int ret = 0;
+ ret |= chmod(newPath.c_str(), fileStat.st_mode);
+ ret |= chown(newPath.c_str(), fileStat.st_uid, fileStat.st_gid);
+ if (0 != ret) {
+ LoggerE("Error while changing ownership/permissions [%s]", GetErrorString(errno).c_str());
+ remove(newPath.c_str());
+ error_cb(FilesystemError::Other);
+ return;
+ }
+
+ if (0 != remove(oldPath.c_str())) {
+ LoggerE("Error while removing file [%s]", GetErrorString(errno).c_str());
+ remove(newPath.c_str());
+ error_cb(FilesystemError::Other);
+ return;
}
- } else {
- LoggerE("Cannot rename file: %s", GetErrorString(errno).c_str());
- error_cb(FilesystemError::Other);
}
+
+ success_cb(FilesystemStat::getStat(newPath));
}
void FilesystemManager::ReadDir(