aboutsummaryrefslogtreecommitdiff
path: root/libsylph
diff options
context:
space:
mode:
authorhiro <hiro@ee746299-78ed-0310-b773-934348b2243d>2009-03-13 09:26:42 +0000
committerhiro <hiro@ee746299-78ed-0310-b773-934348b2243d>2009-03-13 09:26:42 +0000
commit502215cf02f913469e562c9d13f3a9c5a465413d (patch)
tree2eed9ade823231397fd0985f013d7fe1afab05cc /libsylph
parentdfad6357498ce8f7c0f051027dec550449c5b143 (diff)
win32: use CreateHardLink().
git-svn-id: svn://sylpheed.sraoss.jp/sylpheed/trunk@2117 ee746299-78ed-0310-b773-934348b2243d
Diffstat (limited to 'libsylph')
-rw-r--r--libsylph/mh.c6
-rw-r--r--libsylph/utils.c110
-rw-r--r--libsylph/utils.h7
3 files changed, 110 insertions, 13 deletions
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