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, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
19 * Author: Matthias Clasen
27 #include <sys/types.h>
42 /* GResource functions {{{1 */
44 get_resource (const gchar *file)
53 if (g_file_get_contents (file, &content, &size, NULL))
55 data = g_bytes_new_take (content, size);
56 resource = g_resource_new_from_data (data, NULL);
64 list_resource (GResource *resource,
78 children = g_resource_enumerate_children (resource, path, 0, &error);
81 g_printerr ("%s\n", error->message);
85 for (i = 0; children[i]; i++)
87 child = g_strconcat (path, children[i], NULL);
89 len = MIN (strlen (child), strlen (prefix));
90 if (strncmp (child, prefix, len) != 0)
93 if (g_resource_get_info (resource, child, 0, &size, &flags, NULL))
96 g_print ("%s%s%6"G_GSIZE_FORMAT " %s %s\n", section, section[0] ? " " : "", size, flags & G_RESOURCE_FLAGS_COMPRESSED ? "c" : "u", child);
98 g_print ("%s\n", child);
101 list_resource (resource, child, section, prefix, details);
105 g_strfreev (children);
109 extract_resource (GResource *resource,
114 bytes = g_resource_lookup_data (resource, path, 0, NULL);
120 data = g_bytes_get_data (bytes, &size);
121 written = fwrite (data, 1, size, stdout);
123 g_printerr ("Data truncated\n");
124 g_bytes_unref (bytes);
128 g_printerr ("Can't find resource path %s\n", path);
132 /* Elf functions {{{1 */
137 get_elf (const gchar *file,
142 if (elf_version (EV_CURRENT) == EV_NONE )
145 *fd = open (file, O_RDONLY);
149 elf = elf_begin (*fd, ELF_C_READ, NULL);
153 if (elf_kind (elf) != ELF_K_ELF)
159 typedef gboolean (*SectionCallback) (GElf_Shdr *shdr,
164 elf_foreach_resource_section (Elf *elf,
165 SectionCallback callback,
168 size_t shstrndx, shnum;
171 GElf_Shdr *shdr, shdr_mem;
172 const gchar *section_name;
174 elf_getshdrstrndx (elf, &shstrndx);
175 g_assert (shstrndx >= 0);
177 elf_getshdrnum (elf, &shnum);
178 g_assert (shnum >= 0);
180 for (scnidx = 1; scnidx < shnum; scnidx++)
182 scn = elf_getscn (elf, scnidx);
186 shdr = gelf_getshdr (scn, &shdr_mem);
190 if (shdr->sh_type != SHT_PROGBITS)
193 section_name = elf_strptr (elf, shstrndx, shdr->sh_name);
194 if (section_name == NULL ||
195 !g_str_has_prefix (section_name, ".gresource."))
198 if (!callback (shdr, section_name + strlen (".gresource."), data))
204 resource_from_section (GElf_Shdr *shdr,
207 gsize page_size, page_offset;
213 page_size = sysconf(_SC_PAGE_SIZE);
214 page_offset = shdr->sh_offset % page_size;
215 contents = mmap (NULL, shdr->sh_size + page_offset,
216 PROT_READ, MAP_PRIVATE, fd, shdr->sh_offset - page_offset);
217 if (contents != MAP_FAILED)
221 bytes = g_bytes_new_static (contents + page_offset, shdr->sh_size);
222 resource = g_resource_new_from_data (bytes, NULL);
223 g_bytes_unref (bytes);
227 g_printerr ("Can't mmap resource section");
236 const gchar *section;
243 list_resources_cb (GElf_Shdr *shdr,
244 const gchar *section,
247 CallbackData *d = data;
250 if (d->section && strcmp (section, d->section) != 0)
255 resource = resource_from_section (shdr, d->fd);
256 list_resource (resource, "/",
257 d->section ? "" : section,
260 g_resource_unref (resource);
269 elf_list_resources (Elf *elf,
271 const gchar *section,
278 data.section = section;
280 data.details = details;
283 elf_foreach_resource_section (elf, list_resources_cb, &data);
286 g_printerr ("Can't find resource section %s\n", section);
290 extract_resource_cb (GElf_Shdr *shdr,
291 const gchar *section,
294 CallbackData *d = data;
297 if (d->section && strcmp (section, d->section) != 0)
302 resource = resource_from_section (shdr, d->fd);
303 extract_resource (resource, d->path);
304 g_resource_unref (resource);
310 elf_extract_resource (Elf *elf,
312 const gchar *section,
318 data.section = section;
322 elf_foreach_resource_section (elf, extract_resource_cb, &data);
325 g_printerr ("Can't find resource section %s\n", section);
329 print_section_name (GElf_Shdr *shdr,
333 g_print ("%s\n", name);
337 #endif /* HAVE_LIBELF */
339 /* Toplevel commands {{{1 */
342 cmd_sections (const gchar *file,
343 const gchar *section,
354 if ((elf = get_elf (file, &fd)))
356 elf_foreach_resource_section (elf, print_section_name, NULL);
364 if ((resource = get_resource (file)))
367 g_resource_unref (resource);
371 g_printerr ("Don't know how to handle %s\n", file);
373 g_printerr ("gresource is built without elf support\n");
379 cmd_list (const gchar *file,
380 const gchar *section,
391 if ((elf = get_elf (file, &fd)))
393 elf_list_resources (elf, fd, section, path ? path : "", details);
401 if ((resource = get_resource (file)))
403 list_resource (resource, "/", "", path ? path : "", details);
404 g_resource_unref (resource);
408 g_printerr ("Don't know how to handle %s\n", file);
410 g_printerr ("gresource is built without elf support\n");
416 cmd_extract (const gchar *file,
417 const gchar *section,
428 if ((elf = get_elf (file, &fd)))
430 elf_extract_resource (elf, fd, section, path);
438 if ((resource = get_resource (file)))
440 extract_resource (resource, path);
441 g_resource_unref (resource);
445 g_printerr ("Don't know how to handle %s\n", file);
447 g_printerr ("gresource is built without elf support\n");
453 cmd_help (gboolean requested,
454 const gchar *command)
456 const gchar *description;
457 const gchar *synopsis;
463 string = g_string_new (NULL);
468 else if (strcmp (command, "help") == 0)
470 description = _("Print help");
471 synopsis = _("[COMMAND]");
474 else if (strcmp (command, "sections") == 0)
476 description = _("List sections containing resources in an elf FILE");
477 synopsis = _("FILE");
480 else if (strcmp (command, "list") == 0)
482 description = _("List resources\n"
483 "If SECTION is given, only list resources in this section\n"
484 "If PATH is given, only list matching resources");
485 synopsis = _("FILE [PATH]");
486 option = g_strdup_printf ("[--section %s]", _("SECTION"));
489 else if (strcmp (command, "details") == 0)
491 description = _("List resources with details\n"
492 "If SECTION is given, only list resources in this section\n"
493 "If PATH is given, only list matching resources\n"
494 "Details include the section, size and compression");
495 synopsis = _("FILE [PATH]");
496 option = g_strdup_printf ("[--section %s]", _("SECTION"));
499 else if (strcmp (command, "extract") == 0)
501 description = _("Extract a resource file to stdout");
502 synopsis = _("FILE PATH");
503 option = g_strdup_printf ("[--section %s]", _("SECTION"));
508 g_string_printf (string, _("Unknown command %s\n\n"), command);
515 g_string_append (string,
517 " gresource [--section SECTION] COMMAND [ARGS...]\n"
520 " help Show this information\n"
521 " sections List resource sections\n"
522 " list List resources\n"
523 " details List resources with details\n"
524 " extract Extract a resource\n"
526 "Use 'gresource help COMMAND' to get detailed help.\n\n"));
530 g_string_append_printf (string, _("Usage:\n gresource %s%s%s %s\n\n%s\n\n"),
531 option ? option : "", option ? " " : "", command, synopsis[0] ? synopsis : "", description);
533 g_string_append (string, _("Arguments:\n"));
536 g_string_append (string,
537 _(" SECTION An (optional) elf section name\n"));
539 if (strstr (synopsis, _("[COMMAND]")))
540 g_string_append (string,
541 _(" COMMAND The (optional) command to explain\n"));
543 if (strstr (synopsis, _("FILE")))
545 if (strcmp (command, "sections") == 0)
546 g_string_append (string,
547 _(" FILE An elf file (a binary or a shared library)\n"));
549 g_string_append (string,
550 _(" FILE An elf file (a binary or a shared library)\n"
551 " or a compiled resource file\n"));
554 if (strstr (synopsis, _("[PATH]")))
555 g_string_append (string,
556 _(" PATH An (optional) resource path (may be partial)\n"));
557 else if (strstr (synopsis, _("PATH")))
558 g_string_append (string,
559 _(" PATH A resource path\n"));
561 g_string_append (string, "\n");
565 g_print ("%s", string->str);
567 g_printerr ("%s\n", string->str);
570 g_string_free (string, TRUE);
572 return requested ? 0 : 1;
578 main (int argc, char *argv[])
580 gchar *section = NULL;
581 gboolean details = FALSE;
582 void (* function) (const gchar *, const gchar *, const gchar *, gboolean);
585 extern gchar *_glib_get_locale_dir (void);
589 setlocale (LC_ALL, "");
590 textdomain (GETTEXT_PACKAGE);
593 tmp = _glib_get_locale_dir ();
594 bindtextdomain (GETTEXT_PACKAGE, tmp);
597 bindtextdomain (GETTEXT_PACKAGE, GLIB_LOCALE_DIR);
600 #ifdef HAVE_BIND_TEXTDOMAIN_CODESET
601 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: */