diff options
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | src/db-artwork-writer.c | 14 | ||||
-rw-r--r-- | src/itdb_itunesdb.c | 81 | ||||
-rw-r--r-- | src/itdb_private.h | 3 |
4 files changed, 66 insertions, 41 deletions
@@ -1,4 +1,13 @@ 2007-11-15 Christophe Fergeau <teuf@gnome.org> + + * src/itdb_private.h: + * src/itdb_itunesdb.c: add itdb_file_set_contents to workaround a + rename issue on sshfs (existing files on the FS can't be + atomatically erased during a rename). Use it in wcontents_write + * src/db-artwork-writer.c: use itdb_file_set_contents to write the + ArtworkDB + +2007-11-15 Christophe Fergeau <teuf@gnome.org> * src/db-artwork-writer.c: * src/db-parse-context.c: diff --git a/src/db-artwork-writer.c b/src/db-artwork-writer.c index 6de0c80..fd19d8a 100644 --- a/src/db-artwork-writer.c +++ b/src/db-artwork-writer.c @@ -34,6 +34,8 @@ #include "db-image-parser.h" #include "itdb_endianness.h" +#include <glib/gstdio.h> + #include <errno.h> #include <fcntl.h> #include <string.h> @@ -65,13 +67,13 @@ typedef struct _iPodBuffer iPodBuffer; static gboolean ipod_gstring_flush (struct iPodSharedDataBuffer *shared, GError **error) { - gboolean result; + gboolean success; - result = g_file_set_contents (shared->filename, - shared->data->str, shared->data->len, - error); - if (!result) { - return FALSE; + success = itdb_file_set_contents (shared->filename, + shared->data->str, shared->data->len, + error); + if (!success) { + return FALSE; } g_string_free (shared->data, TRUE); g_free (shared->filename); diff --git a/src/itdb_itunesdb.c b/src/itdb_itunesdb.c index 325e90a..cb1b79e 100644 --- a/src/itdb_itunesdb.c +++ b/src/itdb_itunesdb.c @@ -4842,44 +4842,12 @@ static WContents *wcontents_new (const gchar *filename) * cts->error accordingly. */ static gboolean wcontents_write (WContents *cts) { - int fd; - g_return_val_if_fail (cts, FALSE); g_return_val_if_fail (cts->filename, FALSE); - fd = creat (cts->filename, S_IRWXU|S_IRWXG|S_IRWXO); - - if (fd == -1) - { - cts->error = g_error_new (G_FILE_ERROR, - g_file_error_from_errno (errno), - _("Opening of '%s' for writing failed (%s)."), - cts->filename, g_strerror (errno)); - return FALSE; - } - if (cts->contents && cts->pos) - { - ssize_t written = write (fd, cts->contents, cts->pos); - if (written == -1) - { - cts->error = g_error_new (G_FILE_ERROR, - g_file_error_from_errno (errno), - _("Writing to '%s' failed (%s)."), - cts->filename, g_strerror (errno)); - close (fd); - return FALSE; - } - } - fd = close (fd); - if (fd == -1) - { - cts->error = g_error_new (G_FILE_ERROR, - g_file_error_from_errno (errno), - _("Writing to '%s' failed (%s)."), - cts->filename, g_strerror (errno)); - return FALSE; - } - return TRUE; + cts->error = NULL; + return itdb_file_set_contents (cts->filename, cts->contents, + cts->pos, &cts->error); } @@ -6159,6 +6127,49 @@ gboolean itdb_cp (const gchar *from_file, const gchar *to_file, } +G_GNUC_INTERNAL gboolean +itdb_file_set_contents (const char *filename, + const char *data, gssize len, + GError **error) +{ + gchar *backup; + gboolean success; + + /* sshfs (which is used to access iPhones/iTouches) can't successfully + * rename a file if the destination file already exist. + * We first move away the existing file to workaround that limitation + * */ + if (g_file_test (filename, G_FILE_TEST_EXISTS)) { + gint result; + backup = g_strdup_printf ("%sXXXXXX", filename); + result = g_rename (filename, backup); + if (result != 0) { + g_free (backup); + return FALSE; + } + } else { + backup = NULL; + } + + success = g_file_set_contents (filename, data, len, error); + if (!success) { + if (backup != NULL) { + g_rename (backup, filename); + g_free (backup); + } + return FALSE; + } + + /* File saving was + * ok, clean up our + * mess */ + if (backup != NULL) { + g_unlink (backup); + g_free (backup); + } + + return TRUE; +} /** diff --git a/src/itdb_private.h b/src/itdb_private.h index 1ce36da..7e9e410 100644 --- a/src/itdb_private.h +++ b/src/itdb_private.h @@ -156,4 +156,7 @@ G_GNUC_INTERNAL guint64 device_time_time_t_to_mac (Itdb_Device *device, time_t timet); G_GNUC_INTERNAL gint itdb_musicdirs_number_by_mountpoint (const gchar *mountpoint); G_GNUC_INTERNAL gboolean itdb_device_requires_checksum (Itdb_Device *device); +G_GNUC_INTERNAL gboolean itdb_file_set_contents (const char *filename, + const char *data, gssize len, + GError **error); #endif |