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