X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fupdateiconcache.c;h=effea7c6c605611f497d77b8ec83f515001ab861;hb=feb64f40b0f50735104da0a7fdafbe480763c180;hp=15fc7ca80af1fafcdf736d9ace79666b12576ae4;hpb=ff89f9050dc14b54292185747e72b01f8bc88c86;p=~andy%2Fgtk diff --git a/gtk/updateiconcache.c b/gtk/updateiconcache.c index 15fc7ca80..effea7c6c 100644 --- a/gtk/updateiconcache.c +++ b/gtk/updateiconcache.c @@ -12,12 +12,10 @@ * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * License along with this library. If not, see . */ -#include +#include "config.h" #include #include @@ -31,6 +29,7 @@ #endif #include #ifdef _MSC_VER +#include #include #else #include @@ -72,11 +71,11 @@ static gchar *var_name = "-"; #include -static struct stat cache_stat; +static GStatBuf cache_stat; static gboolean cache_up_to_date; static int check_dir_mtime (const char *dir, - const struct stat *sb, + const GStatBuf *sb, int tf) { if (tf != FTW_NS && sb->st_mtime > cache_stat.st_mtime) @@ -89,9 +88,9 @@ static int check_dir_mtime (const char *dir, return 0; } - gboolean - is_cache_up_to_date (const gchar *path) - { +static gboolean +is_cache_up_to_date (const gchar *path) +{ gchar *cache_path; gint retval; @@ -117,7 +116,7 @@ static int check_dir_mtime (const char *dir, gboolean is_cache_up_to_date (const gchar *path) { - struct stat path_stat, cache_stat; + GStatBuf path_stat, cache_stat; gchar *cache_path; int retval; @@ -488,7 +487,7 @@ maybe_cache_image_data (Image *image, idata2 = g_hash_table_lookup (image_data_hash, path2); if (idata && idata2 && idata != idata2) - g_error (_("different idatas found for symlinked '%s' and '%s'\n"), + g_error ("different idatas found for symlinked '%s' and '%s'\n", path, path2); if (idata && !idata2) @@ -548,7 +547,7 @@ maybe_cache_icon_data (Image *image, idata2 = g_hash_table_lookup (icon_data_hash, path2); if (idata && idata2 && idata != idata2) - g_error (_("different idatas found for symlinked '%s' and '%s'\n"), + g_error ("different idatas found for symlinked '%s' and '%s'\n", path, path2); if (idata && !idata2) @@ -575,6 +574,23 @@ maybe_cache_icon_data (Image *image, } } +/** + * Finds all dir separators and replaces them with '/'. + * This makes sure that only /-separated paths are written in cache files, + * maintaining compatibility with theme index files that use slashes as + * directory separators on all platforms. + */ +static void +replace_backslashes_with_slashes (gchar *path) +{ + size_t i; + if (path == NULL) + return; + for (i = 0; path[i]; i++) + if (G_IS_DIR_SEPARATOR (path[i])) + path[i] = '/'; +} + static GList * scan_directory (const gchar *base_path, const gchar *subdir, @@ -589,7 +605,7 @@ scan_directory (const gchar *base_path, gboolean dir_added = FALSE; guint dir_index = 0xffff; - dir_path = g_build_filename (base_path, subdir, NULL); + dir_path = g_build_path ("/", base_path, subdir, NULL); /* FIXME: Use the gerror */ dir = g_dir_open (dir_path, 0, NULL); @@ -608,13 +624,14 @@ scan_directory (const gchar *base_path, gchar *basename, *dot; path = g_build_filename (dir_path, name, NULL); + retval = g_file_test (path, G_FILE_TEST_IS_DIR); if (retval) { gchar *subsubdir; if (subdir) - subsubdir = g_build_filename (subdir, name, NULL); + subsubdir = g_build_path ("/", subdir, name, NULL); else subsubdir = g_strdup (name); directories = scan_directory (base_path, subsubdir, files, @@ -1094,14 +1111,13 @@ write_bucket (FILE *cache, HashNode *node, int *offset) int name_offset; int name_size; int image_list_offset; - int tmp; int i, len; GList *list; g_assert (*offset == ftell (cache)); node->offset = *offset; - + get_single_node_size (node, &node_size, &image_data_size); g_assert (node_size % 4 == 0); g_assert (image_data_size % 4 == 0); @@ -1109,16 +1125,16 @@ write_bucket (FILE *cache, HashNode *node, int *offset) next_offset = *offset + node_size + image_data_size; /* Chain offset */ if (node->next != NULL) - { - if (!write_card32 (cache, next_offset)) - return FALSE; - } + { + if (!write_card32 (cache, next_offset)) + return FALSE; + } else - { - if (!write_card32 (cache, 0xffffffff)) - return FALSE; - } - + { + if (!write_card32 (cache, 0xffffffff)) + return FALSE; + } + name_size = 0; name_offset = find_string (node->name); if (name_offset <= 0) @@ -1128,113 +1144,110 @@ write_bucket (FILE *cache, HashNode *node, int *offset) add_string (node->name, name_offset); } if (!write_card32 (cache, name_offset)) - return FALSE; - + return FALSE; + image_list_offset = *offset + 12 + name_size; if (!write_card32 (cache, image_list_offset)) - return FALSE; - + return FALSE; + /* Icon name */ if (name_size > 0) { if (!write_string (cache, node->name)) - return FALSE; + return FALSE; } /* Image list */ len = g_list_length (node->image_list); if (!write_card32 (cache, len)) - return FALSE; - - /* Image data goes right after the image list */ - tmp = image_list_offset + 4 + len * 8; + return FALSE; list = node->image_list; data_offset = image_data_offset; for (i = 0; i < len; i++) - { - Image *image = list->data; - int image_data_size = get_image_data_size (image); + { + Image *image = list->data; + int image_data_size = get_image_data_size (image); - /* Directory index */ - if (!write_card16 (cache, image->dir_index)) - return FALSE; - - /* Flags */ - if (!write_card16 (cache, image->flags)) - return FALSE; + /* Directory index */ + if (!write_card16 (cache, image->dir_index)) + return FALSE; - /* Image data offset */ - if (image_data_size > 0) - { - if (!write_card32 (cache, data_offset)) - return FALSE; - data_offset += image_data_size; - } - else - { - if (!write_card32 (cache, 0)) - return FALSE; - } + /* Flags */ + if (!write_card16 (cache, image->flags)) + return FALSE; - list = list->next; - } + /* Image data offset */ + if (image_data_size > 0) + { + if (!write_card32 (cache, data_offset)) + return FALSE; + data_offset += image_data_size; + } + else + { + if (!write_card32 (cache, 0)) + return FALSE; + } + + list = list->next; + } /* Now write the image data */ list = node->image_list; for (i = 0; i < len; i++, list = list->next) - { - Image *image = list->data; - int pixel_data_size = get_image_pixel_data_size (image); - int meta_data_size = get_image_meta_data_size (image); + { + Image *image = list->data; + int pixel_data_size = get_image_pixel_data_size (image); + int meta_data_size = get_image_meta_data_size (image); - if (get_image_data_size (image) == 0) - continue; + if (get_image_data_size (image) == 0) + continue; - /* Pixel data */ - if (pixel_data_size > 0) - { - image->image_data->offset = image_data_offset + 8; - if (!write_card32 (cache, image->image_data->offset)) - return FALSE; - } - else - { - if (!write_card32 (cache, (guint32) image->image_data ? image->image_data->offset : 0)) - return FALSE; - } + /* Pixel data */ + if (pixel_data_size > 0) + { + image->image_data->offset = image_data_offset + 8; + if (!write_card32 (cache, image->image_data->offset)) + return FALSE; + } + else + { + if (!write_card32 (cache, (guint32) (image->image_data ? image->image_data->offset : 0))) + return FALSE; + } - if (meta_data_size > 0) - { - image->icon_data->offset = image_data_offset + pixel_data_size + 8; - if (!write_card32 (cache, image->icon_data->offset)) - return FALSE; - } - else - { - if (!write_card32 (cache, image->icon_data ? image->icon_data->offset : 0)) - return FALSE; - } + if (meta_data_size > 0) + { + image->icon_data->offset = image_data_offset + pixel_data_size + 8; + if (!write_card32 (cache, image->icon_data->offset)) + return FALSE; + } + else + { + if (!write_card32 (cache, image->icon_data ? image->icon_data->offset : 0)) + return FALSE; + } - if (pixel_data_size > 0) - { - if (!write_image_data (cache, image->image_data, image->image_data->offset)) - return FALSE; - } - - if (meta_data_size > 0) - { + if (pixel_data_size > 0) + { + if (!write_image_data (cache, image->image_data, image->image_data->offset)) + return FALSE; + } + + if (meta_data_size > 0) + { if (!write_icon_data (cache, image->icon_data, image->icon_data->offset)) return FALSE; } - image_data_offset += pixel_data_size + meta_data_size + 8; - } - + image_data_offset += pixel_data_size + meta_data_size + 8; + } + *offset = next_offset; node = node->next; } - + return TRUE; } @@ -1414,12 +1427,38 @@ validate_file (const gchar *file) if (!_gtk_icon_cache_validate (&info)) { - g_mapped_file_free (map); + g_mapped_file_unref (map); return FALSE; } - g_mapped_file_free (map); + g_mapped_file_unref (map); + + return TRUE; +} +/** + * safe_fclose: + * @f: A FILE* stream, must have underlying fd + * + * Unix defaults for data preservation after system crash + * are unspecified, and many systems will eat your data + * in this situation unless you explicitly fsync(). + * + * Returns: %TRUE on success, %FALSE on failure, and will set errno() + */ +static gboolean +safe_fclose (FILE *f) +{ + int fd = fileno (f); + g_assert (fd >= 0); + if (fflush (f) == EOF) + return FALSE; +#ifndef G_OS_WIN32 + if (fsync (fd) < 0) + return FALSE; +#endif + if (fclose (f) == EOF) + return FALSE; return TRUE; } @@ -1431,12 +1470,12 @@ build_cache (const gchar *path) gchar *bak_cache_path = NULL; #endif GHashTable *files; - gboolean retval; FILE *cache; - struct stat path_stat, cache_stat; + GStatBuf path_stat, cache_stat; struct utimbuf utime_buf; GList *directories = NULL; int fd; + int retry_count = 0; #ifndef G_OS_WIN32 mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; #else @@ -1447,9 +1486,17 @@ build_cache (const gchar *path) #endif tmp_cache_path = g_build_filename (path, "."CACHE_NAME, NULL); + cache_path = g_build_filename (path, CACHE_NAME, NULL); - if ((fd = open (tmp_cache_path, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC | _O_BINARY, mode)) == -1) +opentmp: + if ((fd = g_open (tmp_cache_path, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC | _O_BINARY, mode)) == -1) { + if (force_update && retry_count == 0) + { + retry_count++; + g_remove (tmp_cache_path); + goto opentmp; + } g_printerr (_("Failed to open file %s : %s\n"), tmp_cache_path, g_strerror (errno)); exit (1); } @@ -1474,34 +1521,35 @@ build_cache (const gchar *path) /* Empty table, just close and remove the file */ fclose (cache); - close (fd); g_unlink (tmp_cache_path); + g_unlink (cache_path); exit (0); } /* FIXME: Handle failure */ - retval = write_file (cache, files, directories); - fclose (cache); - close (fd); + if (!write_file (cache, files, directories)) + { + g_unlink (tmp_cache_path); + exit (1); + } - g_list_foreach (directories, (GFunc)g_free, NULL); - g_list_free (directories); - - if (!retval) + if (!safe_fclose (cache)) { + g_printerr (_("Failed to write cache file: %s\n"), g_strerror (errno)); g_unlink (tmp_cache_path); exit (1); } + cache = NULL; + + g_list_free_full (directories, g_free); if (!validate_file (tmp_cache_path)) { g_printerr (_("The generated cache was invalid.\n")); - //g_unlink (tmp_cache_path); + /*g_unlink (tmp_cache_path);*/ exit (1); } - cache_path = g_build_filename (path, CACHE_NAME, NULL); - #ifdef G_OS_WIN32 if (g_file_test (cache_path, G_FILE_TEST_EXISTS)) { @@ -1509,9 +1557,11 @@ build_cache (const gchar *path) g_unlink (bak_cache_path); if (g_rename (cache_path, bak_cache_path) == -1) { + int errsv = errno; + g_printerr (_("Could not rename %s to %s: %s, removing %s then.\n"), cache_path, bak_cache_path, - g_strerror (errno), + g_strerror (errsv), cache_path); g_unlink (cache_path); bak_cache_path = NULL; @@ -1521,16 +1571,22 @@ build_cache (const gchar *path) if (g_rename (tmp_cache_path, cache_path) == -1) { + int errsv = errno; + g_printerr (_("Could not rename %s to %s: %s\n"), tmp_cache_path, cache_path, - g_strerror (errno)); + g_strerror (errsv)); g_unlink (tmp_cache_path); #ifdef G_OS_WIN32 if (bak_cache_path != NULL) if (g_rename (bak_cache_path, cache_path) == -1) - g_printerr (_("Could not rename %s back to %s: %s.\n"), - bak_cache_path, cache_path, - g_strerror (errno)); + { + errsv = errno; + + g_printerr (_("Could not rename %s back to %s: %s.\n"), + bak_cache_path, cache_path, + g_strerror (errsv)); + } #endif exit (1); } @@ -1547,8 +1603,12 @@ build_cache (const gchar *path) utime_buf.actime = path_stat.st_atime; utime_buf.modtime = cache_stat.st_mtime; +#if GLIB_CHECK_VERSION (2, 17, 1) + g_utime (path, &utime_buf); +#else utime (path, &utime_buf); - +#endif + if (!quiet) g_printerr (_("Cache file created successfully.\n")); } @@ -1637,8 +1697,12 @@ main (int argc, char **argv) setlocale (LC_ALL, ""); +#ifdef ENABLE_NLS bindtextdomain (GETTEXT_PACKAGE, GTK_LOCALEDIR); +#ifdef HAVE_BIND_TEXTDOMAIN_CODESET bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); +#endif +#endif context = g_option_context_new ("ICONPATH"); g_option_context_add_main_entries (context, args, GETTEXT_PACKAGE); @@ -1676,7 +1740,7 @@ main (int argc, char **argv) { if (path) { - g_printerr (_("No theme index file.")); + g_printerr (_("No theme index file.\n")); } else { @@ -1690,7 +1754,7 @@ main (int argc, char **argv) if (!force_update && is_cache_up_to_date (path)) return 0; - g_type_init (); + replace_backslashes_with_slashes (path); build_cache (path); if (strcmp (var_name, "-") != 0)