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>
40 #include <glib/gstdio.h>
43 /* GResource functions {{{1 */
45 get_resource (const gchar
*file
)
54 if (g_file_get_contents (file
, &content
, &size
, NULL
))
56 data
= g_bytes_new_take (content
, size
);
57 resource
= g_resource_new_from_data (data
, NULL
);
65 list_resource (GResource
*resource
,
79 children
= g_resource_enumerate_children (resource
, path
, 0, &error
);
82 g_printerr ("%s\n", error
->message
);
86 for (i
= 0; children
[i
]; i
++)
88 child
= g_strconcat (path
, children
[i
], NULL
);
90 len
= MIN (strlen (child
), strlen (prefix
));
91 if (strncmp (child
, prefix
, len
) != 0)
94 if (g_resource_get_info (resource
, child
, 0, &size
, &flags
, NULL
))
97 g_print ("%s%s%6"G_GSIZE_FORMAT
" %s %s\n", section
, section
[0] ? " " : "", size
, flags
& G_RESOURCE_FLAGS_COMPRESSED
? "c" : "u", child
);
99 g_print ("%s\n", child
);
102 list_resource (resource
, child
, section
, prefix
, details
);
106 g_strfreev (children
);
110 extract_resource (GResource
*resource
,
115 bytes
= g_resource_lookup_data (resource
, path
, 0, NULL
);
121 data
= g_bytes_get_data (bytes
, &size
);
122 written
= fwrite (data
, 1, size
, stdout
);
124 g_printerr ("Data truncated\n");
125 g_bytes_unref (bytes
);
129 g_printerr ("Can't find resource path %s\n", path
);
133 /* Elf functions {{{1 */
138 get_elf (const gchar
*file
,
143 if (elf_version (EV_CURRENT
) == EV_NONE
)
146 *fd
= g_open (file
, O_RDONLY
, 0);
150 elf
= elf_begin (*fd
, ELF_C_READ
, NULL
);
154 if (elf_kind (elf
) != ELF_K_ELF
)
160 typedef gboolean (*SectionCallback
) (GElf_Shdr
*shdr
,
165 elf_foreach_resource_section (Elf
*elf
,
166 SectionCallback callback
,
169 size_t shstrndx
, shnum
;
172 GElf_Shdr
*shdr
, shdr_mem
;
173 const gchar
*section_name
;
175 elf_getshdrstrndx (elf
, &shstrndx
);
176 g_assert (shstrndx
>= 0);
178 elf_getshdrnum (elf
, &shnum
);
179 g_assert (shnum
>= 0);
181 for (scnidx
= 1; scnidx
< shnum
; scnidx
++)
183 scn
= elf_getscn (elf
, scnidx
);
187 shdr
= gelf_getshdr (scn
, &shdr_mem
);
191 if (shdr
->sh_type
!= SHT_PROGBITS
)
194 section_name
= elf_strptr (elf
, shstrndx
, shdr
->sh_name
);
195 if (section_name
== NULL
||
196 !g_str_has_prefix (section_name
, ".gresource."))
199 if (!callback (shdr
, section_name
+ strlen (".gresource."), data
))
205 resource_from_section (GElf_Shdr
*shdr
,
208 gsize page_size
, page_offset
;
214 page_size
= sysconf(_SC_PAGE_SIZE
);
215 page_offset
= shdr
->sh_offset
% page_size
;
216 contents
= mmap (NULL
, shdr
->sh_size
+ page_offset
,
217 PROT_READ
, MAP_PRIVATE
, fd
, shdr
->sh_offset
- page_offset
);
218 if (contents
!= MAP_FAILED
)
222 bytes
= g_bytes_new_static (contents
+ page_offset
, shdr
->sh_size
);
223 resource
= g_resource_new_from_data (bytes
, NULL
);
224 g_bytes_unref (bytes
);
228 g_printerr ("Can't mmap resource section");
237 const gchar
*section
;
244 list_resources_cb (GElf_Shdr
*shdr
,
245 const gchar
*section
,
248 CallbackData
*d
= data
;
251 if (d
->section
&& strcmp (section
, d
->section
) != 0)
256 resource
= resource_from_section (shdr
, d
->fd
);
257 list_resource (resource
, "/",
258 d
->section
? "" : section
,
261 g_resource_unref (resource
);
270 elf_list_resources (Elf
*elf
,
272 const gchar
*section
,
279 data
.section
= section
;
281 data
.details
= details
;
284 elf_foreach_resource_section (elf
, list_resources_cb
, &data
);
287 g_printerr ("Can't find resource section %s\n", section
);
291 extract_resource_cb (GElf_Shdr
*shdr
,
292 const gchar
*section
,
295 CallbackData
*d
= data
;
298 if (d
->section
&& strcmp (section
, d
->section
) != 0)
303 resource
= resource_from_section (shdr
, d
->fd
);
304 extract_resource (resource
, d
->path
);
305 g_resource_unref (resource
);
311 elf_extract_resource (Elf
*elf
,
313 const gchar
*section
,
319 data
.section
= section
;
323 elf_foreach_resource_section (elf
, extract_resource_cb
, &data
);
326 g_printerr ("Can't find resource section %s\n", section
);
330 print_section_name (GElf_Shdr
*shdr
,
334 g_print ("%s\n", name
);
338 #endif /* HAVE_LIBELF */
340 /* Toplevel commands {{{1 */
343 cmd_sections (const gchar
*file
,
344 const gchar
*section
,
355 if ((elf
= get_elf (file
, &fd
)))
357 elf_foreach_resource_section (elf
, print_section_name
, NULL
);
365 if ((resource
= get_resource (file
)))
368 g_resource_unref (resource
);
372 g_printerr ("Don't know how to handle %s\n", file
);
374 g_printerr ("gresource is built without elf support\n");
380 cmd_list (const gchar
*file
,
381 const gchar
*section
,
392 if ((elf
= get_elf (file
, &fd
)))
394 elf_list_resources (elf
, fd
, section
, path
? path
: "", details
);
402 if ((resource
= get_resource (file
)))
404 list_resource (resource
, "/", "", path
? path
: "", details
);
405 g_resource_unref (resource
);
409 g_printerr ("Don't know how to handle %s\n", file
);
411 g_printerr ("gresource is built without elf support\n");
417 cmd_extract (const gchar
*file
,
418 const gchar
*section
,
429 if ((elf
= get_elf (file
, &fd
)))
431 elf_extract_resource (elf
, fd
, section
, path
);
439 if ((resource
= get_resource (file
)))
441 extract_resource (resource
, path
);
442 g_resource_unref (resource
);
446 g_printerr ("Don't know how to handle %s\n", file
);
448 g_printerr ("gresource is built without elf support\n");
454 cmd_help (gboolean requested
,
455 const gchar
*command
)
457 const gchar
*description
;
458 const gchar
*synopsis
;
464 string
= g_string_new (NULL
);
469 else if (strcmp (command
, "help") == 0)
471 description
= _("Print help");
472 synopsis
= _("[COMMAND]");
475 else if (strcmp (command
, "sections") == 0)
477 description
= _("List sections containing resources in an elf FILE");
478 synopsis
= _("FILE");
481 else if (strcmp (command
, "list") == 0)
483 description
= _("List resources\n"
484 "If SECTION is given, only list resources in this section\n"
485 "If PATH is given, only list matching resources");
486 synopsis
= _("FILE [PATH]");
487 option
= g_strdup_printf ("[--section %s]", _("SECTION"));
490 else if (strcmp (command
, "details") == 0)
492 description
= _("List resources with details\n"
493 "If SECTION is given, only list resources in this section\n"
494 "If PATH is given, only list matching resources\n"
495 "Details include the section, size and compression");
496 synopsis
= _("FILE [PATH]");
497 option
= g_strdup_printf ("[--section %s]", _("SECTION"));
500 else if (strcmp (command
, "extract") == 0)
502 description
= _("Extract a resource file to stdout");
503 synopsis
= _("FILE PATH");
504 option
= g_strdup_printf ("[--section %s]", _("SECTION"));
509 g_string_printf (string
, _("Unknown command %s\n\n"), command
);
516 g_string_append (string
,
518 " gresource [--section SECTION] COMMAND [ARGS...]\n"
521 " help Show this information\n"
522 " sections List resource sections\n"
523 " list List resources\n"
524 " details List resources with details\n"
525 " extract Extract a resource\n"
527 "Use 'gresource help COMMAND' to get detailed help.\n\n"));
531 g_string_append_printf (string
, _("Usage:\n gresource %s%s%s %s\n\n%s\n\n"),
532 option
? option
: "", option
? " " : "", command
, synopsis
[0] ? synopsis
: "", description
);
534 g_string_append (string
, _("Arguments:\n"));
537 g_string_append (string
,
538 _(" SECTION An (optional) elf section name\n"));
540 if (strstr (synopsis
, _("[COMMAND]")))
541 g_string_append (string
,
542 _(" COMMAND The (optional) command to explain\n"));
544 if (strstr (synopsis
, _("FILE")))
546 if (strcmp (command
, "sections") == 0)
547 g_string_append (string
,
548 _(" FILE An elf file (a binary or a shared library)\n"));
550 g_string_append (string
,
551 _(" FILE An elf file (a binary or a shared library)\n"
552 " or a compiled resource file\n"));
555 if (strstr (synopsis
, _("[PATH]")))
556 g_string_append (string
,
557 _(" PATH An (optional) resource path (may be partial)\n"));
558 else if (strstr (synopsis
, _("PATH")))
559 g_string_append (string
,
560 _(" PATH A resource path\n"));
562 g_string_append (string
, "\n");
566 g_print ("%s", string
->str
);
568 g_printerr ("%s\n", string
->str
);
571 g_string_free (string
, TRUE
);
573 return requested
? 0 : 1;
579 main (int argc
, char *argv
[])
581 gchar
*section
= NULL
;
582 gboolean details
= FALSE
;
583 void (* function
) (const gchar
*, const gchar
*, const gchar
*, gboolean
);
586 extern gchar
*_glib_get_locale_dir (void);
590 setlocale (LC_ALL
, "");
591 textdomain (GETTEXT_PACKAGE
);
594 tmp
= _glib_get_locale_dir ();
595 bindtextdomain (GETTEXT_PACKAGE
, tmp
);
598 bindtextdomain (GETTEXT_PACKAGE
, GLIB_LOCALE_DIR
);
601 #ifdef HAVE_BIND_TEXTDOMAIN_CODESET
602 bind_textdomain_codeset (GETTEXT_PACKAGE
, "UTF-8");
608 return cmd_help (FALSE
, NULL
);
610 if (argc
> 3 && strcmp (argv
[1], "--section") == 0)
617 if (strcmp (argv
[1], "help") == 0)
618 return cmd_help (TRUE
, argv
[2]);
620 else if (argc
== 4 && strcmp (argv
[1], "extract") == 0)
621 function
= cmd_extract
;
623 else if (argc
== 3 && strcmp (argv
[1], "sections") == 0)
624 function
= cmd_sections
;
626 else if ((argc
== 3 || argc
== 4) && strcmp (argv
[1], "list") == 0)
631 else if ((argc
== 3 || argc
== 4) && strcmp (argv
[1], "details") == 0)
637 return cmd_help (FALSE
, argv
[1]);
639 (* function
) (argv
[2], section
, argc
> 3 ? argv
[3] : NULL
, details
);
644 /* vim:set foldmethod=marker: */