diff options
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | libsylph/mh.c | 6 | ||||
-rw-r--r-- | libsylph/utils.c | 110 | ||||
-rw-r--r-- | libsylph/utils.h | 7 |
4 files changed, 116 insertions, 13 deletions
@@ -1,3 +1,9 @@ +2008-03-13 + + * libsylph/utils.[ch] + libsylph/mh.c: win32: use CreateHardLink() if available. + It will improve file I/O on receive. + 2008-02-27 * libsylph/prefs_common.c diff --git a/libsylph/mh.c b/libsylph/mh.c index 386d7557..4b68cd3a 100644 --- a/libsylph/mh.c +++ b/libsylph/mh.c @@ -459,18 +459,14 @@ static gint mh_add_msgs(Folder *folder, FolderItem *dest, GSList *file_list, if (first_ == 0 || first_ > dest->last_num + 1) first_ = dest->last_num + 1; -#ifdef G_OS_UNIX - if (link(fileinfo->file, destfile) < 0) { -#endif + if (g_link(fileinfo->file, destfile) < 0) { if (copy_file(fileinfo->file, destfile, TRUE) < 0) { g_warning(_("can't copy message %s to %s\n"), fileinfo->file, destfile); g_free(destfile); return -1; } -#ifdef G_OS_UNIX } -#endif g_free(destfile); dest->last_num++; diff --git a/libsylph/utils.c b/libsylph/utils.c index fddd0433..208458ea 100644 --- a/libsylph/utils.c +++ b/libsylph/utils.c @@ -42,6 +42,9 @@ #include <time.h> #ifdef G_OS_WIN32 +#ifndef WINVER +# define WINVER 0x0500 +#endif # include <windows.h> # include <wchar.h> # include <direct.h> @@ -149,6 +152,63 @@ gint g_chmod(const gchar *path, gint mode) } #endif /* GLIB_CHECK_VERSION && G_OS_UNIX */ +gint g_link(const gchar *src, const gchar *dest) +{ +#ifdef G_OS_WIN32 + wchar_t *wsrc; + wchar_t *wdest; + gint retval; + gint save_errno; + + wsrc = g_utf8_to_utf16(src, -1, NULL, NULL, NULL); + if (wsrc == NULL) { + errno = EINVAL; + return -1; + } + wdest = g_utf8_to_utf16(dest, -1, NULL, NULL, NULL); + if (wdest == NULL) { + g_free(wsrc); + errno = EINVAL; + return -1; + } + + errno = 0; + if (CreateHardLinkW(wdest, wsrc, NULL)) { + retval = 0; + /* debug_print("hard link created: %s -> %s\n", src, dest); */ + } else { + retval = -1; + switch (GetLastError()) { + case ERROR_FILE_NOT_FOUND: + case ERROR_PATH_NOT_FOUND: + errno = ENOENT; break; + case ERROR_ACCESS_DENIED: + case ERROR_LOCK_VIOLATION: + case ERROR_SHARING_VIOLATION: + errno = EACCES; break; + case ERROR_NOT_SAME_DEVICE: + errno = EXDEV; break; + case ERROR_FILE_EXISTS: + case ERROR_ALREADY_EXISTS: + errno = EEXIST; break; + case ERROR_TOO_MANY_LINKS: + errno = EMLINK; break; + default: + errno = EIO; break; + } + } + save_errno = errno; + + g_free(wdest); + g_free(wsrc); + + errno = save_errno; + return retval; +#else + return link(src, dest); +#endif +} + void list_free_strings(GList *list) { list = g_list_first(list); @@ -2641,17 +2701,54 @@ gint rename_force(const gchar *oldpath, const gchar *newpath) gint copy_file(const gchar *src, const gchar *dest, gboolean keep_backup) { +#ifdef G_OS_WIN32 + wchar_t *wsrc; + wchar_t *wdest; + gchar *dest_bak = NULL; + gboolean err = FALSE; + + wsrc = g_utf8_to_utf16(src, -1, NULL, NULL, NULL); + if (wsrc == NULL) { + return -1; + } + wdest = g_utf8_to_utf16(dest, -1, NULL, NULL, NULL); + if (wdest == NULL) { + g_free(wsrc); + return -1; + } + + if (keep_backup == FALSE) { + if (CopyFileW(wsrc, wdest, FALSE) == 0) + err = TRUE; + g_free(wdest); + g_free(wsrc); + return err ? -1 : 0; + } + + if (is_file_exist(dest)) { + dest_bak = g_strconcat(dest, ".bak", NULL); + if (rename_force(dest, dest_bak) < 0) { + FILE_OP_ERROR(dest, "rename"); + g_free(dest_bak); + g_free(wdest); + g_free(wsrc); + return -1; + } + } + + if (CopyFileW(wsrc, wdest, FALSE) == 0) + err = TRUE; + + g_free(wdest); + g_free(wsrc); +#else gint srcfd, destfd; gint n_read; gchar buf[BUFFSIZE]; gchar *dest_bak = NULL; gboolean err = FALSE; -#ifdef G_OS_WIN32 - if ((srcfd = g_open(src, O_RDONLY | O_BINARY, 0600)) < 0) { -#else if ((srcfd = g_open(src, O_RDONLY, 0600)) < 0) { -#endif FILE_OP_ERROR(src, "open"); return -1; } @@ -2665,11 +2762,7 @@ gint copy_file(const gchar *src, const gchar *dest, gboolean keep_backup) } } -#ifdef G_OS_WIN32 - if ((destfd = g_open(dest, O_WRONLY | O_CREAT | O_BINARY, 0600)) < 0) { -#else if ((destfd = g_open(dest, O_WRONLY | O_CREAT, 0600)) < 0) { -#endif FILE_OP_ERROR(dest, "open"); close(srcfd); if (dest_bak) { @@ -2707,6 +2800,7 @@ gint copy_file(const gchar *src, const gchar *dest, gboolean keep_backup) err = TRUE; } close(srcfd); +#endif if (err) { g_unlink(dest); diff --git a/libsylph/utils.h b/libsylph/utils.h index 25978160..6788c3d6 100644 --- a/libsylph/utils.h +++ b/libsylph/utils.h @@ -67,6 +67,13 @@ gint g_chmod (const gchar *path, #endif /* !GLIB_CHECK_VERSION */ +#ifdef G_OS_UNIX +#define g_link link +#else +gint g_link (const gchar *src, + const gchar *dest); +#endif + /* The AC_CHECK_SIZEOF() in configure fails for some machines. * we provide some fallback values here */ #if !SIZEOF_UNSIGNED_SHORT |