| 
									
										
										
										
											2012-01-22 02:39:11 -05:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright © 2012 Red Hat, Inc | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This library is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU Lesser General Public | 
					
						
							|  |  |  |  * License as published by the Free Software Foundation; either | 
					
						
							|  |  |  |  * version 2 of the licence, or (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This library is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
					
						
							|  |  |  |  * Lesser General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU Lesser 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. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Author: Matthias Clasen | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "config.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #include <stdio.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <sys/types.h>
 | 
					
						
							|  |  |  | #include <sys/stat.h>
 | 
					
						
							|  |  |  | #include <fcntl.h>
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							| 
									
										
										
										
											2012-01-25 10:28:27 +01:00
										 |  |  | #include <locale.h>
 | 
					
						
							| 
									
										
										
										
											2012-01-22 02:39:11 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | #ifdef HAVE_LIBELF
 | 
					
						
							|  |  |  | #include <libelf.h>
 | 
					
						
							|  |  |  | #include <gelf.h>
 | 
					
						
							| 
									
										
										
										
											2012-02-01 09:10:29 +02:00
										 |  |  | #include <sys/mman.h>
 | 
					
						
							| 
									
										
										
										
											2012-01-22 02:39:11 -05:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <gio/gio.h>
 | 
					
						
							|  |  |  | #include <gi18n.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* GResource functions {{{1 */ | 
					
						
							|  |  |  | static GResource * | 
					
						
							|  |  |  | get_resource (const gchar *file) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   gchar *content; | 
					
						
							|  |  |  |   gsize size; | 
					
						
							|  |  |  |   GResource *resource; | 
					
						
							|  |  |  |   GBytes *data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   resource = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (g_file_get_contents (file, &content, &size, NULL)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       data = g_bytes_new_take (content, size); | 
					
						
							|  |  |  |       resource = g_resource_new_from_data (data, NULL); | 
					
						
							|  |  |  |       g_bytes_unref (data); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return resource; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | list_resource (GResource   *resource, | 
					
						
							|  |  |  |                const gchar *path, | 
					
						
							|  |  |  |                const gchar *section, | 
					
						
							|  |  |  |                const gchar *prefix, | 
					
						
							|  |  |  |                gboolean     details) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   gchar **children; | 
					
						
							|  |  |  |   gsize size; | 
					
						
							|  |  |  |   guint32 flags; | 
					
						
							|  |  |  |   gint i; | 
					
						
							|  |  |  |   gchar *child; | 
					
						
							|  |  |  |   GError *error = NULL; | 
					
						
							|  |  |  |   gint len; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   children = g_resource_enumerate_children (resource, path, 0, &error); | 
					
						
							|  |  |  |   if (error) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       g_printerr ("%s\n", error->message); | 
					
						
							|  |  |  |       g_error_free (error); | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   for (i = 0; children[i]; i++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       child = g_strconcat (path, children[i], NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       len = MIN (strlen (child), strlen (prefix)); | 
					
						
							|  |  |  |       if (strncmp (child, prefix, len) != 0) | 
					
						
							|  |  |  |         continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (g_resource_get_info (resource, child, 0, &size, &flags, NULL)) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           if (details) | 
					
						
							| 
									
										
										
										
											2012-01-24 14:18:12 +01:00
										 |  |  |             g_print ("%s%s%6"G_GSIZE_FORMAT " %s %s\n", section, section[0] ? " " : "", size, flags & G_RESOURCE_FLAGS_COMPRESSED ? "c" : "u", child); | 
					
						
							| 
									
										
										
										
											2012-01-22 02:39:11 -05:00
										 |  |  |           else | 
					
						
							|  |  |  |             g_print ("%s\n", child); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |         list_resource (resource, child, section, prefix, details); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       g_free (child); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   g_strfreev (children); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | extract_resource (GResource   *resource, | 
					
						
							|  |  |  |                   const gchar *path) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   GBytes *bytes; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   bytes = g_resource_lookup_data (resource, path, 0, NULL); | 
					
						
							|  |  |  |   if (bytes != NULL) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       gconstpointer data; | 
					
						
							|  |  |  |       gsize size, written; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       data = g_bytes_get_data (bytes, &size); | 
					
						
							|  |  |  |       written = fwrite (data, 1, size, stdout); | 
					
						
							|  |  |  |       if (written < size) | 
					
						
							|  |  |  |         g_printerr ("Data truncated\n"); | 
					
						
							|  |  |  |       g_bytes_unref (bytes); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       g_printerr ("Can't find resource path %s\n", path); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Elf functions {{{1 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef HAVE_LIBELF
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static Elf * | 
					
						
							|  |  |  | get_elf (const gchar *file, | 
					
						
							|  |  |  |          gint        *fd) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   Elf *elf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (elf_version (EV_CURRENT) == EV_NONE ) | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   *fd = open (file, O_RDONLY); | 
					
						
							|  |  |  |   if (*fd < 0) | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   elf = elf_begin (*fd, ELF_C_READ, NULL); | 
					
						
							|  |  |  |   if (elf == NULL) | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (elf_kind (elf) != ELF_K_ELF) | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return elf; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef gboolean (*SectionCallback) (GElf_Shdr   *shdr, | 
					
						
							|  |  |  |                                      const gchar *name, | 
					
						
							|  |  |  |                                      gpointer     data); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | elf_foreach_resource_section (Elf             *elf, | 
					
						
							|  |  |  |                               SectionCallback  callback, | 
					
						
							|  |  |  |                               gpointer         data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   size_t shstrndx, shnum; | 
					
						
							|  |  |  |   size_t scnidx; | 
					
						
							|  |  |  |   Elf_Scn *scn; | 
					
						
							|  |  |  |   GElf_Shdr *shdr, shdr_mem; | 
					
						
							|  |  |  |   const gchar *section_name; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   elf_getshdrstrndx (elf, &shstrndx); | 
					
						
							|  |  |  |   g_assert (shstrndx >= 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   elf_getshdrnum (elf, &shnum); | 
					
						
							|  |  |  |   g_assert (shnum >= 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (scnidx = 1; scnidx < shnum; scnidx++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       scn = elf_getscn (elf, scnidx); | 
					
						
							|  |  |  |       if (scn == NULL) | 
					
						
							|  |  |  |         continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       shdr = gelf_getshdr (scn, &shdr_mem); | 
					
						
							|  |  |  |       if (shdr == NULL) | 
					
						
							|  |  |  |         continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (shdr->sh_type != SHT_PROGBITS) | 
					
						
							|  |  |  |         continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       section_name = elf_strptr (elf, shstrndx, shdr->sh_name); | 
					
						
							|  |  |  |       if (section_name == NULL || | 
					
						
							|  |  |  |           !g_str_has_prefix (section_name, ".gresource.")) | 
					
						
							|  |  |  |         continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (!callback (shdr, section_name + strlen (".gresource."), data)) | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static GResource * | 
					
						
							|  |  |  | resource_from_section (GElf_Shdr *shdr, | 
					
						
							|  |  |  |                        int        fd) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   gsize page_size, page_offset; | 
					
						
							|  |  |  |   char *contents; | 
					
						
							|  |  |  |   GResource *resource; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   resource = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   page_size = sysconf(_SC_PAGE_SIZE); | 
					
						
							|  |  |  |   page_offset = shdr->sh_offset % page_size; | 
					
						
							|  |  |  |   contents = mmap (NULL,  shdr->sh_size + page_offset, | 
					
						
							|  |  |  |                    PROT_READ, MAP_PRIVATE, fd, shdr->sh_offset - page_offset); | 
					
						
							|  |  |  |   if (contents != MAP_FAILED) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       GBytes *bytes; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       bytes = g_bytes_new_static (contents + page_offset, shdr->sh_size); | 
					
						
							|  |  |  |       resource = g_resource_new_from_data (bytes, NULL); | 
					
						
							|  |  |  |       g_bytes_unref (bytes); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       g_printerr ("Can't mmap resource section"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return resource; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   int fd; | 
					
						
							|  |  |  |   const gchar *section; | 
					
						
							|  |  |  |   const gchar *path; | 
					
						
							|  |  |  |   gboolean details; | 
					
						
							|  |  |  |   gboolean found; | 
					
						
							|  |  |  | } CallbackData; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static gboolean | 
					
						
							|  |  |  | list_resources_cb (GElf_Shdr   *shdr, | 
					
						
							|  |  |  |                    const gchar *section, | 
					
						
							|  |  |  |                    gpointer     data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   CallbackData *d = data; | 
					
						
							|  |  |  |   GResource *resource; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (d->section && strcmp (section, d->section) != 0) | 
					
						
							|  |  |  |     return TRUE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   d->found = TRUE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   resource = resource_from_section (shdr, d->fd); | 
					
						
							|  |  |  |   list_resource (resource, "/", | 
					
						
							|  |  |  |                  d->section ? "" : section, | 
					
						
							|  |  |  |                  d->path, | 
					
						
							|  |  |  |                  d->details); | 
					
						
							|  |  |  |   g_resource_unref (resource); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (d->section) | 
					
						
							|  |  |  |     return FALSE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return TRUE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | elf_list_resources (Elf         *elf, | 
					
						
							|  |  |  |                     int          fd, | 
					
						
							|  |  |  |                     const gchar *section, | 
					
						
							|  |  |  |                     const gchar *path, | 
					
						
							|  |  |  |                     gboolean     details) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   CallbackData data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   data.fd = fd; | 
					
						
							|  |  |  |   data.section = section; | 
					
						
							|  |  |  |   data.path = path; | 
					
						
							|  |  |  |   data.details = details; | 
					
						
							|  |  |  |   data.found = FALSE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   elf_foreach_resource_section (elf, list_resources_cb, &data); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!data.found) | 
					
						
							|  |  |  |     g_printerr ("Can't find resource section %s\n", section); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static gboolean | 
					
						
							|  |  |  | extract_resource_cb (GElf_Shdr   *shdr, | 
					
						
							|  |  |  |                      const gchar *section, | 
					
						
							|  |  |  |                      gpointer     data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   CallbackData *d = data; | 
					
						
							|  |  |  |   GResource *resource; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (d->section && strcmp (section, d->section) != 0) | 
					
						
							|  |  |  |     return TRUE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   d->found = TRUE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   resource = resource_from_section (shdr, d->fd); | 
					
						
							|  |  |  |   extract_resource (resource, d->path); | 
					
						
							|  |  |  |   g_resource_unref (resource); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return FALSE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | elf_extract_resource (Elf         *elf, | 
					
						
							|  |  |  |                       int          fd, | 
					
						
							|  |  |  |                       const gchar *section, | 
					
						
							|  |  |  |                       const gchar *path) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   CallbackData data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   data.fd = fd; | 
					
						
							|  |  |  |   data.section = section; | 
					
						
							|  |  |  |   data.path = path; | 
					
						
							|  |  |  |   data.found = FALSE; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   elf_foreach_resource_section (elf, extract_resource_cb, &data); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!data.found) | 
					
						
							|  |  |  |     g_printerr ("Can't find resource section %s\n", section); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static gboolean | 
					
						
							|  |  |  | print_section_name (GElf_Shdr   *shdr, | 
					
						
							|  |  |  |                     const gchar *name, | 
					
						
							|  |  |  |                     gpointer     data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   g_print ("%s\n", name); | 
					
						
							|  |  |  |   return TRUE; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif /* HAVE_LIBELF */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Toplevel commands {{{1 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | cmd_sections (const gchar *file, | 
					
						
							|  |  |  |               const gchar *section, | 
					
						
							|  |  |  |               const gchar *path, | 
					
						
							|  |  |  |               gboolean     details) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   GResource *resource; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef HAVE_LIBELF
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Elf *elf; | 
					
						
							|  |  |  |   gint fd; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ((elf = get_elf (file, &fd))) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       elf_foreach_resource_section (elf, print_section_name, NULL); | 
					
						
							|  |  |  |       elf_end (elf); | 
					
						
							|  |  |  |       close (fd); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ((resource = get_resource (file))) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       /* No sections */ | 
					
						
							|  |  |  |       g_resource_unref (resource); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       g_printerr ("Don't know how to handle %s\n", file); | 
					
						
							|  |  |  | #ifndef HAVE_LIBELF
 | 
					
						
							|  |  |  |       g_printerr ("gresource is built without elf support\n"); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | cmd_list (const gchar *file, | 
					
						
							|  |  |  |           const gchar *section, | 
					
						
							|  |  |  |           const gchar *path, | 
					
						
							|  |  |  |           gboolean     details) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   GResource *resource; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef HAVE_LIBELF
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Elf *elf; | 
					
						
							|  |  |  |   int fd; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ((elf = get_elf (file, &fd))) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       elf_list_resources (elf, fd, section, path ? path : "", details); | 
					
						
							|  |  |  |       elf_end (elf); | 
					
						
							|  |  |  |       close (fd); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ((resource = get_resource (file))) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       list_resource (resource, "/", "", path ? path : "", details); | 
					
						
							|  |  |  |       g_resource_unref (resource); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       g_printerr ("Don't know how to handle %s\n", file); | 
					
						
							|  |  |  | #ifndef HAVE_LIBELF
 | 
					
						
							|  |  |  |       g_printerr ("gresource is built without elf support\n"); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | cmd_extract (const gchar *file, | 
					
						
							|  |  |  |              const gchar *section, | 
					
						
							|  |  |  |              const gchar *path, | 
					
						
							|  |  |  |              gboolean     details) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   GResource *resource; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef HAVE_LIBELF
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Elf *elf; | 
					
						
							|  |  |  |   int fd; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ((elf = get_elf (file, &fd))) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       elf_extract_resource (elf, fd, section, path); | 
					
						
							|  |  |  |       elf_end (elf); | 
					
						
							|  |  |  |       close (fd); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ((resource = get_resource (file))) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       extract_resource (resource, path); | 
					
						
							|  |  |  |       g_resource_unref (resource); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       g_printerr ("Don't know how to handle %s\n", file); | 
					
						
							|  |  |  | #ifndef HAVE_LIBELF
 | 
					
						
							|  |  |  |       g_printerr ("gresource is built without elf support\n"); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static gint | 
					
						
							|  |  |  | cmd_help (gboolean     requested, | 
					
						
							|  |  |  |           const gchar *command) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   const gchar *description; | 
					
						
							|  |  |  |   const gchar *synopsis; | 
					
						
							|  |  |  |   gchar *option; | 
					
						
							|  |  |  |   GString *string; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   option = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   string = g_string_new (NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (command == NULL) | 
					
						
							|  |  |  |     ; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   else if (strcmp (command, "help") == 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       description = _("Print help"); | 
					
						
							| 
									
										
										
										
											2012-02-25 10:54:53 -02:00
										 |  |  |       synopsis = _("[COMMAND]"); | 
					
						
							| 
									
										
										
										
											2012-01-22 02:39:11 -05:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   else if (strcmp (command, "sections") == 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       description = _("List sections containing resources in an elf FILE"); | 
					
						
							| 
									
										
										
										
											2012-02-25 10:54:53 -02:00
										 |  |  |       synopsis = _("FILE"); | 
					
						
							| 
									
										
										
										
											2012-01-22 02:39:11 -05:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   else if (strcmp (command, "list") == 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       description = _("List resources\n" | 
					
						
							|  |  |  |                       "If SECTION is given, only list resources in this section\n" | 
					
						
							|  |  |  |                       "If PATH is given, only list matching resources"); | 
					
						
							| 
									
										
										
										
											2012-02-25 10:54:53 -02:00
										 |  |  |       synopsis = _("FILE [PATH]"); | 
					
						
							| 
									
										
										
										
											2012-01-22 02:39:11 -05:00
										 |  |  |       option = g_strdup_printf ("[--section %s]", _("SECTION")); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   else if (strcmp (command, "details") == 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       description = _("List resources with details\n" | 
					
						
							|  |  |  |                       "If SECTION is given, only list resources in this section\n" | 
					
						
							|  |  |  |                       "If PATH is given, only list matching resources\n" | 
					
						
							|  |  |  |                       "Details include the section, size and compression"); | 
					
						
							| 
									
										
										
										
											2012-02-25 10:54:53 -02:00
										 |  |  |       synopsis = _("FILE [PATH]"); | 
					
						
							| 
									
										
										
										
											2012-01-22 02:39:11 -05:00
										 |  |  |       option = g_strdup_printf ("[--section %s]", _("SECTION")); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   else if (strcmp (command, "extract") == 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       description = _("Extract a resource file to stdout"); | 
					
						
							| 
									
										
										
										
											2012-02-25 10:54:53 -02:00
										 |  |  |       synopsis = _("FILE PATH"); | 
					
						
							| 
									
										
										
										
											2012-01-22 02:39:11 -05:00
										 |  |  |       option = g_strdup_printf ("[--section %s]", _("SECTION")); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       g_string_printf (string, _("Unknown command %s\n\n"), command); | 
					
						
							|  |  |  |       requested = FALSE; | 
					
						
							|  |  |  |       command = NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (command == NULL) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       g_string_append (string, | 
					
						
							|  |  |  |       _("Usage:\n" | 
					
						
							|  |  |  |         "  gresource [--section SECTION] COMMAND [ARGS...]\n" | 
					
						
							|  |  |  |         "\n" | 
					
						
							|  |  |  |         "Commands:\n" | 
					
						
							|  |  |  |         "  help                      Show this information\n" | 
					
						
							|  |  |  |         "  sections                  List resource sections\n" | 
					
						
							|  |  |  |         "  list                      List resources\n" | 
					
						
							|  |  |  |         "  details                   List resources with details\n" | 
					
						
							|  |  |  |         "  extract                   Extract a resource\n" | 
					
						
							|  |  |  |         "\n" | 
					
						
							|  |  |  |         "Use 'gresource help COMMAND' to get detailed help.\n\n")); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       g_string_append_printf (string, _("Usage:\n  gresource %s%s%s %s\n\n%s\n\n"), | 
					
						
							| 
									
										
										
										
											2012-02-25 10:54:53 -02:00
										 |  |  |                               option ? option : "", option ? " " : "", command, synopsis[0] ? synopsis : "", description); | 
					
						
							| 
									
										
										
										
											2012-01-22 02:39:11 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |       g_string_append (string, _("Arguments:\n")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (option) | 
					
						
							|  |  |  |         g_string_append (string, | 
					
						
							|  |  |  |                          _("  SECTION   An (optional) elf section name\n")); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-25 10:54:53 -02:00
										 |  |  |       if (strstr (synopsis, _("[COMMAND]"))) | 
					
						
							| 
									
										
										
										
											2012-01-22 02:39:11 -05:00
										 |  |  |         g_string_append (string, | 
					
						
							|  |  |  |                        _("  COMMAND   The (optional) command to explain\n")); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-25 10:54:53 -02:00
										 |  |  |       if (strstr (synopsis, _("FILE"))) | 
					
						
							| 
									
										
										
										
											2012-01-22 02:39:11 -05:00
										 |  |  |         { | 
					
						
							|  |  |  |           if (strcmp (command, "sections") == 0) | 
					
						
							|  |  |  |             g_string_append (string, | 
					
						
							|  |  |  |                              _("  FILE      An elf file (a binary or a shared library)\n")); | 
					
						
							|  |  |  |           else | 
					
						
							|  |  |  |             g_string_append (string, | 
					
						
							|  |  |  |                              _("  FILE      An elf file (a binary or a shared library)\n" | 
					
						
							|  |  |  |                                "            or a compiled resource file\n")); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-25 10:54:53 -02:00
										 |  |  |       if (strstr (synopsis, _("[PATH]"))) | 
					
						
							| 
									
										
										
										
											2012-01-22 02:39:11 -05:00
										 |  |  |         g_string_append (string, | 
					
						
							|  |  |  |                        _("  PATH      An (optional) resource path (may be partial)\n")); | 
					
						
							| 
									
										
										
										
											2012-02-25 10:54:53 -02:00
										 |  |  |       else if (strstr (synopsis, _("PATH"))) | 
					
						
							| 
									
										
										
										
											2012-01-22 02:39:11 -05:00
										 |  |  |         g_string_append (string, | 
					
						
							|  |  |  |                        _("  PATH      A resource path\n")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       g_string_append (string, "\n"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (requested) | 
					
						
							|  |  |  |     g_print ("%s", string->str); | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     g_printerr ("%s\n", string->str); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   g_free (option); | 
					
						
							|  |  |  |   g_string_free (string, TRUE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return requested ? 0 : 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* main {{{1 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							|  |  |  | main (int argc, char *argv[]) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   gchar *section = NULL; | 
					
						
							|  |  |  |   gboolean details = FALSE; | 
					
						
							|  |  |  |   void (* function) (const gchar *, const gchar *, const gchar *, gboolean); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-24 17:37:09 -05:00
										 |  |  | #ifdef G_OS_WIN32
 | 
					
						
							|  |  |  |   extern gchar *_glib_get_locale_dir (void); | 
					
						
							|  |  |  |   gchar *tmp; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   setlocale (LC_ALL, ""); | 
					
						
							|  |  |  |   textdomain (GETTEXT_PACKAGE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef G_OS_WIN32
 | 
					
						
							|  |  |  |   tmp = _glib_get_locale_dir (); | 
					
						
							|  |  |  |   bindtextdomain (GETTEXT_PACKAGE, tmp); | 
					
						
							|  |  |  |   g_free (tmp); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |   bindtextdomain (GETTEXT_PACKAGE, GLIB_LOCALE_DIR); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef HAVE_BIND_TEXTDOMAIN_CODESET
 | 
					
						
							|  |  |  |   bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-22 02:39:11 -05:00
										 |  |  |   g_type_init (); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (argc < 2) | 
					
						
							|  |  |  |     return cmd_help (FALSE, NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (argc > 3 && strcmp (argv[1], "--section") == 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       section = argv[2]; | 
					
						
							|  |  |  |       argv = argv + 2; | 
					
						
							|  |  |  |       argc -= 2; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (strcmp (argv[1], "help") == 0) | 
					
						
							|  |  |  |     return cmd_help (TRUE, argv[2]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   else if (argc == 4 && strcmp (argv[1], "extract") == 0) | 
					
						
							|  |  |  |     function = cmd_extract; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   else if (argc == 3 && strcmp (argv[1], "sections") == 0) | 
					
						
							|  |  |  |     function = cmd_sections; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   else if ((argc == 3 || argc == 4) && strcmp (argv[1], "list") == 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       function = cmd_list; | 
					
						
							|  |  |  |       details = FALSE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else if ((argc == 3 || argc == 4) && strcmp (argv[1], "details") == 0) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       function = cmd_list; | 
					
						
							|  |  |  |       details = TRUE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     return cmd_help (FALSE, argv[1]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   (* function) (argv[2], section, argc > 3 ? argv[3] : NULL, details); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* vim:set foldmethod=marker: */ |