[Mono-dev] [PATCH]System.IO.File.Replace
Attached is a patch that implements the 2.0 method File.IO.File.Replace. http://msdn2.microsoft.com/en-us/library/9etk7xw2.aspx Some implementation details are as follows. -An internal call was added to perform this operation -Most argument validation is performed in managed code. -On windows we call ReplaceFile defined in Kernel32 -On !windows Replace file was implemented in io-layer/io.c *file-io.c: Added ves_icall_System_IO_MonoIO_ReplaceFile to call ReplaceFile Kernel32 on windows or in io-layer. *file-io.h: Added deceleration for ves_icall_System_IO_MonoIO_ReplaceFile *icall-def.h: Register ves_icall_System_IO_MonoIO_ReplaceFile as an internal call. *io.c: Added implementation for ReplaceFile. *io.h: Added deceleration for ReplaceFile method. *File.cs: Add implementation for IO.File.Replace methods. *MonoIO.cs: Declared an internal call for ReplaceFile *FileTest.cs: Added a test for IO.File.Replace. This may be less of a patch request and more of a "Tell me what I did wrong." ;) -bill replaceFile.diff Description: Binary data ___ Mono-devel-list mailing list Mono-devel-list@lists.ximian.com http://lists.ximian.com/mailman/listinfo/mono-devel-list
Re: [Mono-dev] [PATCH]System.IO.File.Replace
Hi Bill, Below are some comments regarding your patch: + +return(ret); +} Don't use parentesis around the return value, it makes things harder to read. +int remain, n; +int buf_size = st_src->st_blksize; +char *buf = (char *) alloca (buf_size); + It's better to avoid alloca for quite a few reasons and on this case, it's better to limit the maximum size of buf_size since it's value is outside mono's control. - -g_free (utf8_src); -g_free (utf8_dest); -close (src_fd); -close (dest_fd); - + +g_free (utf8_replacedFileName); +g_free (utf8_replacementFileName); +g_free (utf8_backupFileName); +close (backup_fd); + Notice here that you're introducing some redudant whitespaces in the empty lines, this should be avoided as it make patches hard to read due to increased noise. Besides that, I have a question. Wouldn't be possible to use sendfile for unix systems? Senfile skip copying data to user space and should be a lot faster than using read/write. Cheers! Rodrigo On 8/15/07, Bill Holmes <[EMAIL PROTECTED]> wrote: > > Attached is a patch that implements the 2.0 method File.IO.File.Replace. > > http://msdn2.microsoft.com/en-us/library/9etk7xw2.aspx > > Some implementation details are as follows. > -An internal call was added to perform this operation > -Most argument validation is performed in managed code. > -On windows we call ReplaceFile defined in Kernel32 > -On !windows Replace file was implemented in io-layer/io.c > > *file-io.c: Added ves_icall_System_IO_MonoIO_ReplaceFile to call > ReplaceFile Kernel32 on windows or in io-layer. > *file-io.h: Added deceleration for ves_icall_System_IO_MonoIO_ReplaceFile > *icall-def.h: Register ves_icall_System_IO_MonoIO_ReplaceFile as an > internal call. > *io.c: Added implementation for ReplaceFile. > *io.h: Added deceleration for ReplaceFile method. > *File.cs: Add implementation for IO.File.Replace methods. > *MonoIO.cs: Declared an internal call for ReplaceFile > *FileTest.cs: Added a test for IO.File.Replace. > > This may be less of a patch request and more of a "Tell me what I did > wrong." ;) > > -bill > > ___ > Mono-devel-list mailing list > Mono-devel-list@lists.ximian.com > http://lists.ximian.com/mailman/listinfo/mono-devel-list > > > ___ Mono-devel-list mailing list Mono-devel-list@lists.ximian.com http://lists.ximian.com/mailman/listinfo/mono-devel-list
Re: [Mono-dev] [PATCH]System.IO.File.Replace
> Besides that, I have a question. Wouldn't be possible to use sendfile for > unix systems? Senfile skip copying data to user space and should be a lot > faster than using read/write. >From man: " Other Unix systems implement sendfile() with different semantics and prototypes. It should not be used in portable programs." and "In Linux 2.4 and earlier, out_fd could refer to a regular file" (in 2.6 it has to be a socket). ___ Mono-devel-list mailing list Mono-devel-list@lists.ximian.com http://lists.ximian.com/mailman/listinfo/mono-devel-list
Re: [Mono-dev] [PATCH]System.IO.File.Replace
Rodrigo, I thought the ()'s around the return was a bit odd myself. But since I did not understand why they were in the existing code I kept the pattern going. I will remove them from my changes. As for the alloca, that too is something I refactored out of the CopyFile method. I agree that can cause problems so I will look for an alternative. do you think I could get away with int buf_size = st_src->st_blksize; if (buf_size > 1024) buf_size = 1024; char *buf = (char *) alloca (buf_size); Or should I switch to dynamic allocation (malloc)? Or should I use dynamic allocation and cap the max? I'll see what I can do to cleanup my messy whitespace. sendfile could be a good solution for this method but as Leszek points out this is probably not a reliable cross platform solution. What I am actually doing here is opening the backup file for read. Then in the event of an error I need to simply restore that file. If I had something like linkFile (int in_fd, const char *path) I would be better off. Thanks so much for you comments. I will make improvements and re-submit. -bill ___ Mono-devel-list mailing list Mono-devel-list@lists.ximian.com http://lists.ximian.com/mailman/listinfo/mono-devel-list
Re: [Mono-dev] [PATCH]System.IO.File.Replace
Hello, > I thought the ()'s around the return was a bit odd myself. But since > I did not understand why they were in the existing code I kept the > pattern going. I will remove them from my changes. The io-layer is an exception to the coding guidelines of Mono. Dick Porter tends to use the return (value) pattern. For the sake of consistency with that code we should probably keep that. Miguel ___ Mono-devel-list mailing list Mono-devel-list@lists.ximian.com http://lists.ximian.com/mailman/listinfo/mono-devel-list
Re: [Mono-dev] [PATCH]System.IO.File.Replace
On 08/15/07 Bill Holmes wrote: > I thought the ()'s around the return was a bit odd myself. But since > I did not understand why they were in the existing code I kept the > pattern going. I will remove them from my changes. Thanks: new code also in the io-layer should follow the mono conventions (we just don't usually go around and fix it to avoid losing th history). > As for the alloca, that too is something I refactored out of the > CopyFile method. I agree that can cause problems so I will look for > an alternative. > > do you think I could get away with > int buf_size = st_src->st_blksize; > if (buf_size > 1024) > buf_size = 1024; > char *buf = (char *) alloca (buf_size); > > Or should I switch to dynamic allocation (malloc)? Or should I use > dynamic allocation and cap the max? Just use malloc: the amount of memory that we'd allow to be allocated with alloca (100-200 bytes) would be useless for this usage. The buffer size should also have a lower and upper limit (8-64 KB is reasonable). lupus -- - [EMAIL PROTECTED] debian/rules [EMAIL PROTECTED] Monkeys do it better ___ Mono-devel-list mailing list Mono-devel-list@lists.ximian.com http://lists.ximian.com/mailman/listinfo/mono-devel-list
Re: [Mono-dev] [PATCH]System.IO.File.Replace
On 08/15/07 Bill Holmes wrote: > Attached is a patch that implements the 2.0 method File.IO.File.Replace. > > http://msdn2.microsoft.com/en-us/library/9etk7xw2.aspx Please mark your patch attachments as text files instead of as binary blobs, thanks! > Index: mono/mono/metadata/file-io.c > === > --- mono/mono/metadata/file-io.c (revision 84157) > +++ mono/mono/metadata/file-io.c (working copy) > @@ -10,6 +10,11 @@ > */ > > #include > + > +#ifdef PLATFORM_WIN32 > +#define _WIN32_WINNT 0x0500 > +#endif > + > #include > #include > #include > @@ -384,6 +389,40 @@ > } > > MonoBoolean > +ves_icall_System_IO_MonoIO_ReplaceFile (MonoString *sourceFileName, > MonoString *destinationFileName, > + MonoString *destinationBackupFileName, > MonoBoolean ignoreMetadataErrors, > + gint32 *error) > +{ > + gboolean ret; > + gunichar2 *utf16_sourceFileName=NULL, *utf16_destinationFileName=NULL, > *utf16_destinationBackupFileName=NULL; > + guint32 replaceFlags = REPLACEFILE_WRITE_THROUGH; > + > + MONO_ARCH_SAVE_REGS; > + > + if(sourceFileName) > + utf16_sourceFileName = mono_string_chars (sourceFileName); > + > + if(destinationFileName) > + utf16_destinationFileName = mono_string_chars > (destinationFileName); > + > + if(destinationBackupFileName) > + utf16_destinationBackupFileName = mono_string_chars > (destinationBackupFileName); > + > + *error=ERROR_SUCCESS; Please make new code follow the mono coding conventions: space before parens, spaces around operators like = etc. > #endif /* _MONO_METADATA_FILEIO_H_ */ > Index: mono/mono/metadata/icall-def.h > === > --- mono/mono/metadata/icall-def.h(revision 84157) > +++ mono/mono/metadata/icall-def.h(working copy) > @@ -270,22 +270,25 @@ > ICALL(MONOIO_16, > "Open(string,System.IO.FileMode,System.IO.FileAccess,System.IO.FileShare,System.IO.FileOptions,System.IO.MonoIOError&)", > ves_icall_System_IO_MonoIO_Open) > ICALL(MONOIO_17, "Read(intptr,byte[],int,int,System.IO.MonoIOError&)", > ves_icall_System_IO_MonoIO_Read) > ICALL(MONOIO_18, "RemoveDirectory(string,System.IO.MonoIOError&)", > ves_icall_System_IO_MonoIO_RemoveDirectory) > -ICALL(MONOIO_19, > "Seek(intptr,long,System.IO.SeekOrigin,System.IO.MonoIOError&)", > ves_icall_System_IO_MonoIO_Seek) As written at the beginning of this file, do not rename all the entries, just add the icall in the correctly sorted place. The sequential name is meanlingless, you could use MONOIO_18M or MONOIO_185 in this case. > +ICALL(MONOIO_31, "get_DirectorySeparatorChar", > ves_icall_System_IO_MonoIO_get_DirectorySeparatorChar) > +ICALL(MONOIO_32, "get_InvalidPathChars", > ves_icall_System_IO_MonoIO_get_InvalidPathChars) > +ICALL(MONOIO_33, "get_PathSeparator", > ves_icall_System_IO_MonoIO_get_PathSeparator) > +ICALL(MONOIO_34, "get_VolumeSeparatorChar", > ves_icall_System_IO_MonoIO_get_VolumeSeparatorChar) > > + > + Please don't add random withspace to the code. > Index: mono/mono/io-layer/io.c > === > --- mono/mono/io-layer/io.c (revision 84157) > +++ mono/mono/io-layer/io.c (working copy) > @@ -1835,6 +1835,51 @@ > return(ret); > } > > +gboolean write_file (int src_fd, int dest_fd, struct stat *st_src, gboolean > report_errors) > +{ > + int remain, n; > + int buf_size = st_src->st_blksize; > + char *buf = (char *) alloca (buf_size); > + > + for (;;) { > + remain = read (src_fd, buf, buf_size); > + > + if (remain < 0) { > + if (errno == EINTR && !_wapi_thread_cur_apc_pending ()) > { > + continue; > + } > + > + if (report_errors) > + _wapi_set_last_error_from_errno (); > + > + return(FALSE); > + } > + > + if (remain == 0) { > + break; > + } > + > + while (remain > 0) { > + if ((n = write (dest_fd, buf, remain)) < 0) { > + if (errno == EINTR && > !_wapi_thread_cur_apc_pending ()) > + continue; > + > + if (report_errors) > + _wapi_set_last_error_from_errno (); > +#ifdef DEBUG > + g_message ("%s: write failed.", __func__); > +#endif > + > + return (FALSE); > + } > + > + remain -= n; > + } > + } > + > + return (TRUE); > +} > + > /** > * CopyFile: > * @name: a pointer to
Re: [Mono-dev] [PATCH]System.IO.File.Replace
All, Here is an updated version of my patch. I apologize in advance if my attachment is a "binary blob" again. I am not quite sure what that meant or what I should do about it. This time I am sending the mail from SUSE so maybe that will help. I have applied the changes mentioned by Rodrigo and Paolo including -removed alloca. -adding gotos to avoid duplicate cleanup code. -fixed numbering oversight in icall-def -formatted the code to follow the coding guidelines. (including the return statements) -cleaned up my white space mess. Round 2. What did I miss this time? ;) Thanks so much for you comments. -bill Index: mono/mono/metadata/file-io.c === --- mono/mono/metadata/file-io.c (revision 84326) +++ mono/mono/metadata/file-io.c (working copy) @@ -10,6 +10,11 @@ */ #include + +#ifdef PLATFORM_WIN32 +#define _WIN32_WINNT 0x0500 +#endif + #include #include #include @@ -384,6 +389,36 @@ } MonoBoolean +ves_icall_System_IO_MonoIO_ReplaceFile (MonoString *sourceFileName, MonoString *destinationFileName, + MonoString *destinationBackupFileName, MonoBoolean ignoreMetadataErrors, + gint32 *error) +{ + gboolean ret; + gunichar2 *utf16_sourceFileName = NULL, *utf16_destinationFileName = NULL, *utf16_destinationBackupFileName = NULL; + guint32 replaceFlags = REPLACEFILE_WRITE_THROUGH; + + MONO_ARCH_SAVE_REGS; + + if (sourceFileName) + utf16_sourceFileName = mono_string_chars (sourceFileName); + if (destinationFileName) + utf16_destinationFileName = mono_string_chars (destinationFileName); + if (destinationBackupFileName) + utf16_destinationBackupFileName = mono_string_chars (destinationBackupFileName); + + *error = ERROR_SUCCESS; + if (ignoreMetadataErrors) + replaceFlags |= REPLACEFILE_IGNORE_MERGE_ERRORS; + + ret = ReplaceFile (utf16_destinationFileName, utf16_sourceFileName, utf16_destinationBackupFileName, + replaceFlags, NULL, NULL); + if (ret == FALSE) + *error = GetLastError (); + + return ret; +} + +MonoBoolean ves_icall_System_IO_MonoIO_CopyFile (MonoString *path, MonoString *dest, MonoBoolean overwrite, gint32 *error) { Index: mono/mono/metadata/file-io.h === --- mono/mono/metadata/file-io.h (revision 84326) +++ mono/mono/metadata/file-io.h (working copy) @@ -230,6 +230,11 @@ extern void ves_icall_System_IO_MonoIO_Unlock (HANDLE handle, gint64 position, gint64 length, gint32 *error) MONO_INTERNAL; +extern MonoBoolean +ves_icall_System_IO_MonoIO_ReplaceFile (MonoString *sourceFileName, MonoString *destinationFileName, + MonoString *destinationBackupFileName, MonoBoolean ignoreMetadataErrors, + gint32 *error) MONO_INTERNAL; + G_END_DECLS #endif /* _MONO_METADATA_FILEIO_H_ */ Index: mono/mono/metadata/icall-def.h === --- mono/mono/metadata/icall-def.h (revision 84326) +++ mono/mono/metadata/icall-def.h (working copy) @@ -270,6 +270,7 @@ ICALL(MONOIO_16, "Open(string,System.IO.FileMode,System.IO.FileAccess,System.IO.FileShare,System.IO.FileOptions,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_Open) ICALL(MONOIO_17, "Read(intptr,byte[],int,int,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_Read) ICALL(MONOIO_18, "RemoveDirectory(string,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_RemoveDirectory) +ICALL(MONOIO_18M, "ReplaceFile(string,string,string,bool,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_ReplaceFile) ICALL(MONOIO_19, "Seek(intptr,long,System.IO.SeekOrigin,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_Seek) ICALL(MONOIO_20, "SetCurrentDirectory(string,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_SetCurrentDirectory) ICALL(MONOIO_21, "SetFileAttributes(string,System.IO.FileAttributes,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_SetFileAttributes) Index: mono/mono/io-layer/io.c === --- mono/mono/io-layer/io.c (revision 84326) +++ mono/mono/io-layer/io.c (working copy) @@ -1835,6 +1835,55 @@ return(ret); } +gboolean write_file (int src_fd, int dest_fd, struct stat *st_src, gboolean report_errors) +{ + int remain, n; + char *buf; + int buf_size = st_src->st_blksize; + gboolean ret = FALSE; + + buf_size = buf_size < 8192 ? 8192 : (buf_size > 65536 ? 65536 : buf_size); + buf = (char *) malloc (buf_size); + + for (;;) { + remain = read (src_fd, buf, buf_size); + if (remain < 0) { + if (errno == EINTR && !_wapi_thread_cur_apc_pending ()) +continue; + + if (report_errors) +_wapi_set_last_error_from_errno (); + + goto write_file_cleanup; + } + if (remain == 0) { + break; + } + + while (remain > 0) { + if ((n = write (dest_fd, buf, remain)) < 0) { +if (errno == EINTR && !_wapi_thread_cur_apc_pending ()) + continue; + +if (report_errors) + _wapi_set_last_error_from_errno (); +#ifdef DE
Re: [Mono-dev] [PATCH]System.IO.File.Replace
On 08/17/07 Bill Holmes wrote: > Here is an updated version of my patch. I apologize in advance if my > attachment is a "binary blob" again. I am not quite sure what that > meant or what I should do about it. This time I am sending the mail > from SUSE so maybe that will help. It looks good now:) Binary blob means that the patch you sent was marked as an attachment of mime-type octect-stream (octect-stream is another name for binary blob) instead of the text file it is. > Index: mono/mono/io-layer/io.c > === > --- mono/mono/io-layer/io.c (revision 84326) > +++ mono/mono/io-layer/io.c (working copy) > @@ -1835,6 +1835,55 @@ > return(ret); > } > > +gboolean write_file (int src_fd, int dest_fd, struct stat *st_src, gboolean > report_errors) > +{ > + int remain, n; > + char *buf; > + int buf_size = st_src->st_blksize; > + gboolean ret = FALSE; > + > + buf_size = buf_size < 8192 ? 8192 : (buf_size > 65536 ? 65536 : > buf_size); > + buf = (char *) malloc (buf_size); > + > + for (;;) { > + remain = read (src_fd, buf, buf_size); > + if (remain < 0) { > + if (errno == EINTR && !_wapi_thread_cur_apc_pending ()) > + continue; > + > + if (report_errors) > + _wapi_set_last_error_from_errno (); > + > + goto write_file_cleanup; > + } > + if (remain == 0) { > + break; > + } > + > + while (remain > 0) { > + if ((n = write (dest_fd, buf, remain)) < 0) { > + if (errno == EINTR && > !_wapi_thread_cur_apc_pending ()) > + continue; > + > + if (report_errors) > + _wapi_set_last_error_from_errno (); > +#ifdef DEBUG > + g_message ("%s: write failed.", __func__); > +#endif > + goto write_file_cleanup; > + } > + > + remain -= n; > + } > + } > + > + ret = TRUE; > + > +write_file_cleanup: > + free (buf); > + return ret ; In this function I wouldn't use goto (I don't think I asked for this change): the cleanup code is very simple. Anyway, this change made me incpect the code more and there seems to be a bug: in the case of a short write, we try to repeatedly write always from the start of the buffer, instead of advancing into it. This causes corruption and needs fixing. > +gchar* convert_arg_to_utf8 (const gunichar2 *arg, const gchar *arg_name) Here and in the other places, put the function name at the start of a line, with the return type and storage type in their own line. Thanks! lupus -- - [EMAIL PROTECTED] debian/rules [EMAIL PROTECTED] Monkeys do it better ___ Mono-devel-list mailing list Mono-devel-list@lists.ximian.com http://lists.ximian.com/mailman/listinfo/mono-devel-list
Re: [Mono-dev] [PATCH]System.IO.File.Replace
goto removed short write case fixed function definition formatting fixed thanks -bill Index: mono/mono/metadata/file-io.c === --- mono/mono/metadata/file-io.c (revision 84466) +++ mono/mono/metadata/file-io.c (working copy) @@ -10,6 +10,11 @@ */ #include + +#ifdef PLATFORM_WIN32 +#define _WIN32_WINNT 0x0500 +#endif + #include #include #include @@ -384,6 +389,36 @@ } MonoBoolean +ves_icall_System_IO_MonoIO_ReplaceFile (MonoString *sourceFileName, MonoString *destinationFileName, + MonoString *destinationBackupFileName, MonoBoolean ignoreMetadataErrors, + gint32 *error) +{ + gboolean ret; + gunichar2 *utf16_sourceFileName = NULL, *utf16_destinationFileName = NULL, *utf16_destinationBackupFileName = NULL; + guint32 replaceFlags = REPLACEFILE_WRITE_THROUGH; + + MONO_ARCH_SAVE_REGS; + + if (sourceFileName) + utf16_sourceFileName = mono_string_chars (sourceFileName); + if (destinationFileName) + utf16_destinationFileName = mono_string_chars (destinationFileName); + if (destinationBackupFileName) + utf16_destinationBackupFileName = mono_string_chars (destinationBackupFileName); + + *error = ERROR_SUCCESS; + if (ignoreMetadataErrors) + replaceFlags |= REPLACEFILE_IGNORE_MERGE_ERRORS; + + ret = ReplaceFile (utf16_destinationFileName, utf16_sourceFileName, utf16_destinationBackupFileName, + replaceFlags, NULL, NULL); + if (ret == FALSE) + *error = GetLastError (); + + return ret; +} + +MonoBoolean ves_icall_System_IO_MonoIO_CopyFile (MonoString *path, MonoString *dest, MonoBoolean overwrite, gint32 *error) { Index: mono/mono/metadata/file-io.h === --- mono/mono/metadata/file-io.h (revision 84466) +++ mono/mono/metadata/file-io.h (working copy) @@ -230,6 +230,11 @@ extern void ves_icall_System_IO_MonoIO_Unlock (HANDLE handle, gint64 position, gint64 length, gint32 *error) MONO_INTERNAL; +extern MonoBoolean +ves_icall_System_IO_MonoIO_ReplaceFile (MonoString *sourceFileName, MonoString *destinationFileName, + MonoString *destinationBackupFileName, MonoBoolean ignoreMetadataErrors, + gint32 *error) MONO_INTERNAL; + G_END_DECLS #endif /* _MONO_METADATA_FILEIO_H_ */ Index: mono/mono/metadata/icall-def.h === --- mono/mono/metadata/icall-def.h (revision 84466) +++ mono/mono/metadata/icall-def.h (working copy) @@ -271,6 +271,7 @@ ICALL(MONOIO_16, "Open(string,System.IO.FileMode,System.IO.FileAccess,System.IO.FileShare,System.IO.FileOptions,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_Open) ICALL(MONOIO_17, "Read(intptr,byte[],int,int,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_Read) ICALL(MONOIO_18, "RemoveDirectory(string,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_RemoveDirectory) +ICALL(MONOIO_18M, "ReplaceFile(string,string,string,bool,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_ReplaceFile) ICALL(MONOIO_19, "Seek(intptr,long,System.IO.SeekOrigin,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_Seek) ICALL(MONOIO_20, "SetCurrentDirectory(string,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_SetCurrentDirectory) ICALL(MONOIO_21, "SetFileAttributes(string,System.IO.FileAttributes,System.IO.MonoIOError&)", ves_icall_System_IO_MonoIO_SetFileAttributes) Index: mono/mono/io-layer/io.c === --- mono/mono/io-layer/io.c (revision 84466) +++ mono/mono/io-layer/io.c (working copy) @@ -1835,6 +1835,56 @@ return(ret); } +gboolean +write_file (int src_fd, int dest_fd, struct stat *st_src, gboolean report_errors) +{ + int remain, n; + char *buf, *wbuf; + int buf_size = st_src->st_blksize; + + buf_size = buf_size < 8192 ? 8192 : (buf_size > 65536 ? 65536 : buf_size); + buf = (char *) malloc (buf_size); + + for (;;) { + remain = read (src_fd, buf, buf_size); + if (remain < 0) { + if (errno == EINTR && !_wapi_thread_cur_apc_pending ()) +continue; + + if (report_errors) +_wapi_set_last_error_from_errno (); + + free (buf); + return FALSE; + } + if (remain == 0) { + break; + } + + wbuf = buf; + while (remain > 0) { + if ((n = write (dest_fd, wbuf, remain)) < 0) { +if (errno == EINTR && !_wapi_thread_cur_apc_pending ()) + continue; + +if (report_errors) + _wapi_set_last_error_from_errno (); +#ifdef DEBUG +g_message ("%s: write failed.", __func__); +#endif +free (buf); +return FALSE; + } + + remain -= n; + wbuf += n; + } + } + + free (buf); + return TRUE ; +} + /** * CopyFile: * @name: a pointer to a NULL-terminated unicode string, that names @@ -1852,10 +1902,8 @@ { gchar *utf8_src, *utf8_dest; int src_fd, dest_fd; - int buf_size; - char *buf; - int remain, n; struct stat st; + gboolean ret = TRUE; if(name==NULL) { #ifdef DEBUG @@ -1945,63 +1993,107 @@ g_free (utf8_src); g_free (u