+ msg_file_priv_t priv = MSG_file_priv(fd);
+ return simcall_file_move(priv->simdata->smx_file, fullpath);
+}
+
+/**
+ * \ingroup msg_file_management
+ * \brief Copy a file to another location on a remote host.
+ * \param file : the file to move
+ * \param host : the remote host where the file has to be copied
+ * \param fullpath : the complete path destination on the remote host
+ * \return If successful, the function returns MSG_OK. Otherwise, it returns
+ * MSG_TASK_CANCELED.
+ */
+msg_error_t MSG_file_rcopy (msg_file_t file, msg_host_t host, const char* fullpath)
+{
+ msg_file_priv_t file_priv = MSG_file_priv(file);
+ sg_size_t read_size;
+
+ /* Find the host where the file is physically located and read it */
+ msg_storage_t storage_src =(msg_storage_t) xbt_lib_get_elm_or_null(storage_lib, file_priv->storageId);
+ msg_storage_priv_t storage_priv_src = MSG_storage_priv(storage_src);
+ msg_host_t attached_host = MSG_get_host_by_name(storage_priv_src->hostname);
+ read_size = simcall_file_read(file_priv->simdata->smx_file, file_priv->size, attached_host);
+
+ /* Find the real host destination where the file will be physically stored */
+ xbt_dict_cursor_t cursor = NULL;
+ char *mount_name, *storage_name, *file_mount_name, *host_name_dest;
+ msg_storage_t storage_dest = NULL;
+ msg_host_t host_dest;
+ size_t longest_prefix_length = 0;
+
+ xbt_dict_t storage_list = simcall_host_get_mounted_storage_list(host);
+ xbt_dict_foreach(storage_list,cursor,mount_name,storage_name){
+ file_mount_name = (char *) xbt_malloc ((strlen(mount_name)+1));
+ strncpy(file_mount_name,fullpath,strlen(mount_name)+1);
+ file_mount_name[strlen(mount_name)] = '\0';
+
+ if(!strcmp(file_mount_name,mount_name) && strlen(mount_name)>longest_prefix_length){
+ /* The current mount name is found in the full path and is bigger than the previous*/
+ longest_prefix_length = strlen(mount_name);
+ storage_dest = (msg_storage_t) xbt_lib_get_elm_or_null(storage_lib, storage_name);
+ }
+ free(file_mount_name);
+ }
+ if(longest_prefix_length>0){
+ /* Mount point found, retrieve the host the storage is attached to */
+ msg_storage_priv_t storage_dest_priv = MSG_storage_priv(storage_dest);
+ host_name_dest = (char*)storage_dest_priv->hostname;
+ host_dest = MSG_get_host_by_name(host_name_dest);
+
+ }else{
+ XBT_WARN("Can't find mount point for '%s' on destination host '%s'", fullpath, SIMIX_host_get_name(host));
+ return MSG_TASK_CANCELED;
+ }
+
+ XBT_DEBUG("Initiate data transfer of %llu bytes between %s and %s.", read_size, storage_priv_src->hostname, host_name_dest);
+ msg_host_t *m_host_list = NULL;
+ m_host_list = calloc(2, sizeof(msg_host_t));
+
+ m_host_list[0] = attached_host;
+ m_host_list[1] = host_dest;
+ double computation_amount[] = { 0, 0 };
+ double communication_amount[] = { 0, (double)read_size, 0, 0 };
+
+ msg_task_t task = MSG_parallel_task_create("file transfer for write", 2, m_host_list, computation_amount, communication_amount, NULL);
+ msg_error_t transfer = MSG_parallel_task_execute(task);
+ MSG_task_destroy(task);
+ free(m_host_list);
+ if(transfer != MSG_OK){
+ if (transfer == MSG_HOST_FAILURE)
+ XBT_WARN("Transfer error, %s remote host just turned off!", host_name_dest);
+ if (transfer == MSG_TASK_CANCELED)
+ XBT_WARN("Transfer error, task has been canceled!");
+
+ return -1;