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);
160 if (elf_kind (elf) != ELF_K_ELF)
170 typedef gboolean (*SectionCallback) (GElf_Shdr *shdr,
175 elf_foreach_resource_section (Elf *elf,
176 SectionCallback callback,
179 size_t shstrndx, shnum;
182 GElf_Shdr *shdr, shdr_mem;
183 const gchar *section_name;
185 elf_getshdrstrndx (elf, &shstrndx);
186 g_assert (shstrndx >= 0);
188 elf_getshdrnum (elf, &shnum);
189 g_assert (shnum >= 0);
191 for (scnidx = 1; scnidx < shnum; scnidx++)
193 scn = elf_getscn (elf, scnidx);
197 shdr = gelf_getshdr (scn, &shdr_mem);
201 if (shdr->sh_type != SHT_PROGBITS)
204 section_name = elf_strptr (elf, shstrndx, shdr->sh_name);
205 if (section_name == NULL ||
206 !g_str_has_prefix (section_name, ".gresource."))
209 if (!callback (shdr, section_name + strlen (".gresource."), data))
215 resource_from_section (GElf_Shdr *shdr,
218 gsize page_size, page_offset;
224 page_size = sysconf(_SC_PAGE_SIZE);
225 page_offset = shdr->sh_offset % page_size;
226 contents = mmap (NULL, shdr->sh_size + page_offset,
227 PROT_READ, MAP_PRIVATE, fd, shdr->sh_offset - page_offset);
228 if (contents != MAP_FAILED)
232 bytes = g_bytes_new_static (contents + page_offset, shdr->sh_size);
233 resource = g_resource_new_from_data (bytes, NULL);
234 g_bytes_unref (bytes);
238 g_printerr ("Can't mmap resource section");
247 const gchar *section;
254 list_resources_cb (GElf_Shdr *shdr,
255 const gchar *section,
258 CallbackData *d = data;
261 if (d->section && strcmp (section, d->section) != 0)
266 resource = resource_from_section (shdr, d->fd);
267 list_resource (resource, "/",
268 d->section ? "" : section,
271 g_resource_unref (resource);
280 elf_list_resources (Elf *elf,
282 const gchar *section,
289 data.section = section;
291 data.details = details;
294 elf_foreach_resource_section (elf, list_resources_cb, &data);
297 g_printerr ("Can't find resource section %s\n", section);
301 extract_resource_cb (GElf_Shdr *shdr,
302 const gchar *section,
305 CallbackData *d = data;
308 if (d->section && strcmp (section, d->section) != 0)
313 resource = resource_from_section (shdr, d->fd);
314 extract_resource (resource, d->path);
315 g_resource_unref (resource);
321 elf_extract_resource (Elf *elf,
323 const gchar *section,
329 data.section = section;
333 elf_foreach_resource_section (elf, extract_resource_cb, &data);
336 g_printerr ("Can't find resource section %s\n", section);
340 print_section_name (GElf_Shdr *shdr,
344 g_print ("%s\n", name);
348 #endif /* HAVE_LIBELF */
350 /* Toplevel commands {{{1 */
353 cmd_sections (const gchar *file,
354 const gchar *section,
365 if ((elf = get_elf (file, &fd)))
367 elf_foreach_resource_section (elf, print_section_name, NULL);
375 if ((resource = get_resource (file)))
378 g_resource_unref (resource);
382 g_printerr ("Don't know how to handle %s\n", file);
384 g_printerr ("gresource is built without elf support\n");
390 cmd_list (const gchar *file,
391 const gchar *section,
402 if ((elf = get_elf (file, &fd)))
404 elf_list_resources (elf, fd, section, path ? path : "", details);
412 if ((resource = get_resource (file)))
414 list_resource (resource, "/", "", path ? path : "", details);
415 g_resource_unref (resource);
419 g_printerr ("Don't know how to handle %s\n", file);
421 g_printerr ("gresource is built without elf support\n");
427 cmd_extract (const gchar *file,
428 const gchar *section,
439 if ((elf = get_elf (file, &fd)))
441 elf_extract_resource (elf, fd, section, path);
449 if ((resource = get_resource (file)))
451 extract_resource (resource, path);
452 g_resource_unref (resource);
456 g_printerr ("Don't know how to handle %s\n", file);
458 g_printerr ("gresource is built without elf support\n");
464 cmd_help (gboolean requested,
465 const gchar *command)
467 const gchar *description;
468 const gchar *synopsis;
474 string = g_string_new (NULL);
479 else if (strcmp (command, "help") == 0)
481 description = _("Print help");
482 synopsis = _("[COMMAND]");
485 else if (strcmp (command, "sections") == 0)
487 description = _("List sections containing resources in an elf FILE");
488 synopsis = _("FILE");
491 else if (strcmp (command, "list") == 0)
493 description = _("List resources\n"
494 "If SECTION is given, only list resources in this section\n"
495 "If PATH is given, only list matching resources");
496 synopsis = _("FILE [PATH]");
497 option = g_strdup_printf ("[--section %s]", _("SECTION"));
500 else if (strcmp (command, "details") == 0)
502 description = _("List resources with details\n"
503 "If SECTION is given, only list resources in this section\n"
504 "If PATH is given, only list matching resources\n"
505 "Details include the section, size and compression");
506 synopsis = _("FILE [PATH]");
507 option = g_strdup_printf ("[--section %s]", _("SECTION"));
510 else if (strcmp (command, "extract") == 0)
512 description = _("Extract a resource file to stdout");
513 synopsis = _("FILE PATH");
514 option = g_strdup_printf ("[--section %s]", _("SECTION"));
519 g_string_printf (string, _("Unknown command %s\n\n"), command);
526 g_string_append (string,
528 " gresource [--section SECTION] COMMAND [ARGS...]\n"
531 " help Show this information\n"
532 " sections List resource sections\n"
533 " list List resources\n"
534 " details List resources with details\n"
535 " extract Extract a resource\n"
537 "Use 'gresource help COMMAND' to get detailed help.\n\n"));
541 g_string_append_printf (string, _("Usage:\n gresource %s%s%s %s\n\n%s\n\n"),
542 option ? option : "", option ? " " : "", command, synopsis[0] ? synopsis : "", description);
544 g_string_append (string, _("Arguments:\n"));
547 g_string_append (string,
548 _(" SECTION An (optional) elf section name\n"));
550 if (strstr (synopsis, _("[COMMAND]")))
551 g_string_append (string,
552 _(" COMMAND The (optional) command to explain\n"));
554 if (strstr (synopsis, _("FILE")))
556 if (strcmp (command, "sections") == 0)
557 g_string_append (string,
558 _(" FILE An elf file (a binary or a shared library)\n"));
560 g_string_append (string,
561 _(" FILE An elf file (a binary or a shared library)\n"
562 " or a compiled resource file\n"));
565 if (strstr (synopsis, _("[PATH]")))
566 g_string_append (string,
567 _(" PATH An (optional) resource path (may be partial)\n"));
568 else if (strstr (synopsis, _("PATH")))
569 g_string_append (string,
570 _(" PATH A resource path\n"));
572 g_string_append (string, "\n");
576 g_print ("%s", string->str);
578 g_printerr ("%s\n", string->str);
581 g_string_free (string, TRUE);
583 return requested ? 0 : 1;
589 main (int argc, char *argv[])
591 gchar *section = NULL;
592 gboolean details = FALSE;
593 void (* function) (const gchar *, const gchar *, const gchar *, gboolean);
599 setlocale (LC_ALL, "");
600 textdomain (GETTEXT_PACKAGE);
603 tmp = _glib_get_locale_dir ();
604 bindtextdomain (GETTEXT_PACKAGE, tmp);
607 bindtextdomain (GETTEXT_PACKAGE, GLIB_LOCALE_DIR);
610 #ifdef HAVE_BIND_TEXTDOMAIN_CODESET
611 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
615 return cmd_help (FALSE, NULL);
617 if (argc > 3 && strcmp (argv[1], "--section") == 0)
624 if (strcmp (argv[1], "help") == 0)
625 return cmd_help (TRUE, argv[2]);
627 else if (argc == 4 && strcmp (argv[1], "extract") == 0)
628 function = cmd_extract;
630 else if (argc == 3 && strcmp (argv[1], "sections") == 0)
631 function = cmd_sections;
633 else if ((argc == 3 || argc == 4) && strcmp (argv[1], "list") == 0)
638 else if ((argc == 3 || argc == 4) && strcmp (argv[1], "details") == 0)
644 return cmd_help (FALSE, argv[1]);
646 (* function) (argv[2], section, argc > 3 ? argv[3] : NULL, details);
651 /* vim:set foldmethod=marker: */