2 * Copyright © 2012 Red Hat, Inc
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the licence, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
17 * Author: Matthias Clasen
25 #include <sys/types.h>
38 #include <glib/gstdio.h>
42 #include "glib/glib-private.h"
45 /* GResource functions {{{1 */
47 get_resource (const gchar *file)
56 if (g_file_get_contents (file, &content, &size, NULL))
58 data = g_bytes_new_take (content, size);
59 resource = g_resource_new_from_data (data, NULL);
67 list_resource (GResource *resource,
81 children = g_resource_enumerate_children (resource, path, 0, &error);
84 g_printerr ("%s\n", error->message);
88 for (i = 0; children[i]; i++)
90 child = g_strconcat (path, children[i], NULL);
92 len = MIN (strlen (child), strlen (prefix));
93 if (strncmp (child, prefix, len) != 0)
96 if (g_resource_get_info (resource, child, 0, &size, &flags, NULL))
99 g_print ("%s%s%6"G_GSIZE_FORMAT " %s %s\n", section, section[0] ? " " : "", size, flags & G_RESOURCE_FLAGS_COMPRESSED ? "c" : "u", child);
101 g_print ("%s\n", child);
104 list_resource (resource, child, section, prefix, details);
108 g_strfreev (children);
112 extract_resource (GResource *resource,
117 bytes = g_resource_lookup_data (resource, path, 0, NULL);
123 data = g_bytes_get_data (bytes, &size);
124 written = fwrite (data, 1, size, stdout);
126 g_printerr ("Data truncated\n");
127 g_bytes_unref (bytes);
131 g_printerr ("Can't find resource path %s\n", path);
135 /* Elf functions {{{1 */
140 get_elf (const gchar *file,
145 if (elf_version (EV_CURRENT) == EV_NONE )
148 *fd = g_open (file, O_RDONLY, 0);
152 elf = elf_begin (*fd, ELF_C_READ, NULL);
156 if (elf_kind (elf) != ELF_K_ELF)
162 typedef gboolean (*SectionCallback) (GElf_Shdr *shdr,
167 elf_foreach_resource_section (Elf *elf,
168 SectionCallback callback,
171 size_t shstrndx, shnum;
174 GElf_Shdr *shdr, shdr_mem;
175 const gchar *section_name;
177 elf_getshdrstrndx (elf, &shstrndx);
178 g_assert (shstrndx >= 0);
180 elf_getshdrnum (elf, &shnum);
181 g_assert (shnum >= 0);
183 for (scnidx = 1; scnidx < shnum; scnidx++)
185 scn = elf_getscn (elf, scnidx);
189 shdr = gelf_getshdr (scn, &shdr_mem);
193 if (shdr->sh_type != SHT_PROGBITS)
196 section_name = elf_strptr (elf, shstrndx, shdr->sh_name);
197 if (section_name == NULL ||
198 !g_str_has_prefix (section_name, ".gresource."))
201 if (!callback (shdr, section_name + strlen (".gresource."), data))
207 resource_from_section (GElf_Shdr *shdr,
210 gsize page_size, page_offset;
216 page_size = sysconf(_SC_PAGE_SIZE);
217 page_offset = shdr->sh_offset % page_size;
218 contents = mmap (NULL, shdr->sh_size + page_offset,
219 PROT_READ, MAP_PRIVATE, fd, shdr->sh_offset - page_offset);
220 if (contents != MAP_FAILED)
224 bytes = g_bytes_new_static (contents + page_offset, shdr->sh_size);
225 resource = g_resource_new_from_data (bytes, NULL);
226 g_bytes_unref (bytes);
230 g_printerr ("Can't mmap resource section");
239 const gchar *section;
246 list_resources_cb (GElf_Shdr *shdr,
247 const gchar *section,
250 CallbackData *d = data;
253 if (d->section && strcmp (section, d->section) != 0)
258 resource = resource_from_section (shdr, d->fd);
259 list_resource (resource, "/",
260 d->section ? "" : section,
263 g_resource_unref (resource);
272 elf_list_resources (Elf *elf,
274 const gchar *section,
281 data.section = section;
283 data.details = details;
286 elf_foreach_resource_section (elf, list_resources_cb, &data);
289 g_printerr ("Can't find resource section %s\n", section);
293 extract_resource_cb (GElf_Shdr *shdr,
294 const gchar *section,
297 CallbackData *d = data;
300 if (d->section && strcmp (section, d->section) != 0)
305 resource = resource_from_section (shdr, d->fd);
306 extract_resource (resource, d->path);
307 g_resource_unref (resource);
313 elf_extract_resource (Elf *elf,
315 const gchar *section,
321 data.section = section;
325 elf_foreach_resource_section (elf, extract_resource_cb, &data);
328 g_printerr ("Can't find resource section %s\n", section);
332 print_section_name (GElf_Shdr *shdr,
336 g_print ("%s\n", name);
340 #endif /* HAVE_LIBELF */
342 /* Toplevel commands {{{1 */
345 cmd_sections (const gchar *file,
346 const gchar *section,
357 if ((elf = get_elf (file, &fd)))
359 elf_foreach_resource_section (elf, print_section_name, NULL);
367 if ((resource = get_resource (file)))
370 g_resource_unref (resource);
374 g_printerr ("Don't know how to handle %s\n", file);
376 g_printerr ("gresource is built without elf support\n");
382 cmd_list (const gchar *file,
383 const gchar *section,
394 if ((elf = get_elf (file, &fd)))
396 elf_list_resources (elf, fd, section, path ? path : "", details);
404 if ((resource = get_resource (file)))
406 list_resource (resource, "/", "", path ? path : "", details);
407 g_resource_unref (resource);
411 g_printerr ("Don't know how to handle %s\n", file);
413 g_printerr ("gresource is built without elf support\n");
419 cmd_extract (const gchar *file,
420 const gchar *section,
431 if ((elf = get_elf (file, &fd)))
433 elf_extract_resource (elf, fd, section, path);
441 if ((resource = get_resource (file)))
443 extract_resource (resource, path);
444 g_resource_unref (resource);
448 g_printerr ("Don't know how to handle %s\n", file);
450 g_printerr ("gresource is built without elf support\n");
456 cmd_help (gboolean requested,
457 const gchar *command)
459 const gchar *description;
460 const gchar *synopsis;
466 string = g_string_new (NULL);
471 else if (strcmp (command, "help") == 0)
473 description = _("Print help");
474 synopsis = _("[COMMAND]");
477 else if (strcmp (command, "sections") == 0)
479 description = _("List sections containing resources in an elf FILE");
480 synopsis = _("FILE");
483 else if (strcmp (command, "list") == 0)
485 description = _("List resources\n"
486 "If SECTION is given, only list resources in this section\n"
487 "If PATH is given, only list matching resources");
488 synopsis = _("FILE [PATH]");
489 option = g_strdup_printf ("[--section %s]", _("SECTION"));
492 else if (strcmp (command, "details") == 0)
494 description = _("List resources with details\n"
495 "If SECTION is given, only list resources in this section\n"
496 "If PATH is given, only list matching resources\n"
497 "Details include the section, size and compression");
498 synopsis = _("FILE [PATH]");
499 option = g_strdup_printf ("[--section %s]", _("SECTION"));
502 else if (strcmp (command, "extract") == 0)
504 description = _("Extract a resource file to stdout");
505 synopsis = _("FILE PATH");
506 option = g_strdup_printf ("[--section %s]", _("SECTION"));
511 g_string_printf (string, _("Unknown command %s\n\n"), command);
518 g_string_append (string,
520 " gresource [--section SECTION] COMMAND [ARGS...]\n"
523 " help Show this information\n"
524 " sections List resource sections\n"
525 " list List resources\n"
526 " details List resources with details\n"
527 " extract Extract a resource\n"
529 "Use 'gresource help COMMAND' to get detailed help.\n\n"));
533 g_string_append_printf (string, _("Usage:\n gresource %s%s%s %s\n\n%s\n\n"),
534 option ? option : "", option ? " " : "", command, synopsis[0] ? synopsis : "", description);
536 g_string_append (string, _("Arguments:\n"));
539 g_string_append (string,
540 _(" SECTION An (optional) elf section name\n"));
542 if (strstr (synopsis, _("[COMMAND]")))
543 g_string_append (string,
544 _(" COMMAND The (optional) command to explain\n"));
546 if (strstr (synopsis, _("FILE")))
548 if (strcmp (command, "sections") == 0)
549 g_string_append (string,
550 _(" FILE An elf file (a binary or a shared library)\n"));
552 g_string_append (string,
553 _(" FILE An elf file (a binary or a shared library)\n"
554 " or a compiled resource file\n"));
557 if (strstr (synopsis, _("[PATH]")))
558 g_string_append (string,
559 _(" PATH An (optional) resource path (may be partial)\n"));
560 else if (strstr (synopsis, _("PATH")))
561 g_string_append (string,
562 _(" PATH A resource path\n"));
564 g_string_append (string, "\n");
568 g_print ("%s", string->str);
570 g_printerr ("%s\n", string->str);
573 g_string_free (string, TRUE);
575 return requested ? 0 : 1;
581 main (int argc, char *argv[])
583 gchar *section = NULL;
584 gboolean details = FALSE;
585 void (* function) (const gchar *, const gchar *, const gchar *, gboolean);
591 setlocale (LC_ALL, "");
592 textdomain (GETTEXT_PACKAGE);
595 tmp = _glib_get_locale_dir ();
596 bindtextdomain (GETTEXT_PACKAGE, tmp);
599 bindtextdomain (GETTEXT_PACKAGE, GLIB_LOCALE_DIR);
602 #ifdef HAVE_BIND_TEXTDOMAIN_CODESET
603 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
607 return cmd_help (FALSE, NULL);
609 if (argc > 3 && strcmp (argv[1], "--section") == 0)
616 if (strcmp (argv[1], "help") == 0)
617 return cmd_help (TRUE, argv[2]);
619 else if (argc == 4 && strcmp (argv[1], "extract") == 0)
620 function = cmd_extract;
622 else if (argc == 3 && strcmp (argv[1], "sections") == 0)
623 function = cmd_sections;
625 else if ((argc == 3 || argc == 4) && strcmp (argv[1], "list") == 0)
630 else if ((argc == 3 || argc == 4) && strcmp (argv[1], "details") == 0)
636 return cmd_help (FALSE, argv[1]);
638 (* function) (argv[2], section, argc > 3 ? argv[3] : NULL, details);
643 /* vim:set foldmethod=marker: */