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.1 of the License, 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)
99 if (g_resource_get_info (resource
, child
, 0, &size
, &flags
, NULL
))
102 g_print ("%s%s%6"G_GSIZE_FORMAT
" %s %s\n", section
, section
[0] ? " " : "", size
, (flags
& G_RESOURCE_FLAGS_COMPRESSED
) ? "c" : "u", child
);
104 g_print ("%s\n", child
);
107 list_resource (resource
, child
, section
, prefix
, details
);
111 g_strfreev (children
);
115 extract_resource (GResource
*resource
,
120 bytes
= g_resource_lookup_data (resource
, path
, 0, NULL
);
126 data
= g_bytes_get_data (bytes
, &size
);
127 written
= fwrite (data
, 1, size
, stdout
);
129 g_printerr ("Data truncated\n");
130 g_bytes_unref (bytes
);
134 /* Elf functions {{{1 */
139 get_elf (const gchar
*file
,
144 if (elf_version (EV_CURRENT
) == EV_NONE
)
147 *fd
= g_open (file
, O_RDONLY
, 0);
151 elf
= elf_begin (*fd
, ELF_C_READ
, NULL
);
159 if (elf_kind (elf
) != ELF_K_ELF
)
169 typedef gboolean (*SectionCallback
) (GElf_Shdr
*shdr
,
174 elf_foreach_resource_section (Elf
*elf
,
175 SectionCallback callback
,
178 size_t shstrndx
, shnum
;
181 GElf_Shdr
*shdr
, shdr_mem
;
182 const gchar
*section_name
;
184 elf_getshdrstrndx (elf
, &shstrndx
);
185 g_assert (shstrndx
>= 0);
187 elf_getshdrnum (elf
, &shnum
);
188 g_assert (shnum
>= 0);
190 for (scnidx
= 1; scnidx
< shnum
; scnidx
++)
192 scn
= elf_getscn (elf
, scnidx
);
196 shdr
= gelf_getshdr (scn
, &shdr_mem
);
200 if (shdr
->sh_type
!= SHT_PROGBITS
)
203 section_name
= elf_strptr (elf
, shstrndx
, shdr
->sh_name
);
204 if (section_name
== NULL
||
205 !g_str_has_prefix (section_name
, ".gresource."))
208 if (!callback (shdr
, section_name
+ strlen (".gresource."), data
))
214 resource_from_section (GElf_Shdr
*shdr
,
217 gsize page_size
, page_offset
;
223 page_size
= sysconf(_SC_PAGE_SIZE
);
224 page_offset
= shdr
->sh_offset
% page_size
;
225 contents
= mmap (NULL
, shdr
->sh_size
+ page_offset
,
226 PROT_READ
, MAP_PRIVATE
, fd
, shdr
->sh_offset
- page_offset
);
227 if (contents
!= MAP_FAILED
)
230 GError
*error
= NULL
;
232 bytes
= g_bytes_new_static (contents
+ page_offset
, shdr
->sh_size
);
233 resource
= g_resource_new_from_data (bytes
, &error
);
234 g_bytes_unref (bytes
);
237 g_printerr ("%s\n", error
->message
);
238 g_error_free (error
);
243 g_printerr ("Can't mmap resource section");
252 const gchar
*section
;
259 list_resources_cb (GElf_Shdr
*shdr
,
260 const gchar
*section
,
263 CallbackData
*d
= data
;
266 if (d
->section
&& strcmp (section
, d
->section
) != 0)
271 resource
= resource_from_section (shdr
, d
->fd
);
272 list_resource (resource
, "/",
273 d
->section
? "" : section
,
276 g_resource_unref (resource
);
285 elf_list_resources (Elf
*elf
,
287 const gchar
*section
,
294 data
.section
= section
;
296 data
.details
= details
;
299 elf_foreach_resource_section (elf
, list_resources_cb
, &data
);
302 g_printerr ("Can't find resource section %s\n", section
);
306 extract_resource_cb (GElf_Shdr
*shdr
,
307 const gchar
*section
,
310 CallbackData
*d
= data
;
313 if (d
->section
&& strcmp (section
, d
->section
) != 0)
318 resource
= resource_from_section (shdr
, d
->fd
);
319 extract_resource (resource
, d
->path
);
320 g_resource_unref (resource
);
329 elf_extract_resource (Elf
*elf
,
331 const gchar
*section
,
337 data
.section
= section
;
341 elf_foreach_resource_section (elf
, extract_resource_cb
, &data
);
344 g_printerr ("Can't find resource section %s\n", section
);
348 print_section_name (GElf_Shdr
*shdr
,
352 g_print ("%s\n", name
);
356 #endif /* HAVE_LIBELF */
358 /* Toplevel commands {{{1 */
361 cmd_sections (const gchar
*file
,
362 const gchar
*section
,
373 if ((elf
= get_elf (file
, &fd
)))
375 elf_foreach_resource_section (elf
, print_section_name
, NULL
);
383 if ((resource
= get_resource (file
)))
386 g_resource_unref (resource
);
390 g_printerr ("Don't know how to handle %s\n", file
);
392 g_printerr ("gresource is built without elf support\n");
398 cmd_list (const gchar
*file
,
399 const gchar
*section
,
409 if ((elf
= get_elf (file
, &fd
)))
411 elf_list_resources (elf
, fd
, section
, path
? path
: "", details
);
419 if ((resource
= get_resource (file
)))
421 list_resource (resource
, "/", "", path
? path
: "", details
);
422 g_resource_unref (resource
);
426 g_printerr ("Don't know how to handle %s\n", file
);
428 g_printerr ("gresource is built without elf support\n");
434 cmd_extract (const gchar
*file
,
435 const gchar
*section
,
446 if ((elf
= get_elf (file
, &fd
)))
448 elf_extract_resource (elf
, fd
, section
, path
);
456 if ((resource
= get_resource (file
)))
458 extract_resource (resource
, path
);
459 g_resource_unref (resource
);
463 g_printerr ("Don't know how to handle %s\n", file
);
465 g_printerr ("gresource is built without elf support\n");
471 cmd_help (gboolean requested
,
472 const gchar
*command
)
474 const gchar
*description
;
475 const gchar
*synopsis
;
481 string
= g_string_new (NULL
);
486 else if (strcmp (command
, "help") == 0)
488 description
= _("Print help");
489 synopsis
= _("[COMMAND]");
492 else if (strcmp (command
, "sections") == 0)
494 description
= _("List sections containing resources in an elf FILE");
495 synopsis
= _("FILE");
498 else if (strcmp (command
, "list") == 0)
500 description
= _("List resources\n"
501 "If SECTION is given, only list resources in this section\n"
502 "If PATH is given, only list matching resources");
503 synopsis
= _("FILE [PATH]");
504 option
= g_strdup_printf ("[--section %s]", _("SECTION"));
507 else if (strcmp (command
, "details") == 0)
509 description
= _("List resources with details\n"
510 "If SECTION is given, only list resources in this section\n"
511 "If PATH is given, only list matching resources\n"
512 "Details include the section, size and compression");
513 synopsis
= _("FILE [PATH]");
514 option
= g_strdup_printf ("[--section %s]", _("SECTION"));
517 else if (strcmp (command
, "extract") == 0)
519 description
= _("Extract a resource file to stdout");
520 synopsis
= _("FILE PATH");
521 option
= g_strdup_printf ("[--section %s]", _("SECTION"));
526 g_string_printf (string
, _("Unknown command %s\n\n"), command
);
533 g_string_append (string
,
535 " gresource [--section SECTION] COMMAND [ARGS…]\n"
538 " help Show this information\n"
539 " sections List resource sections\n"
540 " list List resources\n"
541 " details List resources with details\n"
542 " extract Extract a resource\n"
544 "Use “gresource help COMMAND” to get detailed help.\n\n"));
548 g_string_append_printf (string
, _("Usage:\n gresource %s%s%s %s\n\n%s\n\n"),
549 option
? option
: "", option
? " " : "", command
, synopsis
[0] ? synopsis
: "", description
);
551 g_string_append (string
, _("Arguments:\n"));
554 g_string_append (string
,
555 _(" SECTION An (optional) elf section name\n"));
557 if (strstr (synopsis
, _("[COMMAND]")))
558 g_string_append (string
,
559 _(" COMMAND The (optional) command to explain\n"));
561 if (strstr (synopsis
, _("FILE")))
563 if (strcmp (command
, "sections") == 0)
564 g_string_append (string
,
565 _(" FILE An elf file (a binary or a shared library)\n"));
567 g_string_append (string
,
568 _(" FILE An elf file (a binary or a shared library)\n"
569 " or a compiled resource file\n"));
572 if (strstr (synopsis
, _("[PATH]")))
573 g_string_append (string
,
574 _(" PATH An (optional) resource path (may be partial)\n"));
575 else if (strstr (synopsis
, _("PATH")))
576 g_string_append (string
,
577 _(" PATH A resource path\n"));
579 g_string_append (string
, "\n");
583 g_print ("%s", string
->str
);
585 g_printerr ("%s\n", string
->str
);
588 g_string_free (string
, TRUE
);
590 return requested
? 0 : 1;
596 main (int argc
, char *argv
[])
598 gchar
*section
= NULL
;
599 gboolean details
= FALSE
;
600 void (* function
) (const gchar
*, const gchar
*, const gchar
*, gboolean
);
606 setlocale (LC_ALL
, "");
607 textdomain (GETTEXT_PACKAGE
);
610 tmp
= _glib_get_locale_dir ();
611 bindtextdomain (GETTEXT_PACKAGE
, tmp
);
614 bindtextdomain (GETTEXT_PACKAGE
, GLIB_LOCALE_DIR
);
617 #ifdef HAVE_BIND_TEXTDOMAIN_CODESET
618 bind_textdomain_codeset (GETTEXT_PACKAGE
, "UTF-8");
622 return cmd_help (FALSE
, NULL
);
624 if (argc
> 3 && strcmp (argv
[1], "--section") == 0)
631 if (strcmp (argv
[1], "help") == 0)
632 return cmd_help (TRUE
, argv
[2]);
634 else if (argc
== 4 && strcmp (argv
[1], "extract") == 0)
635 function
= cmd_extract
;
637 else if (argc
== 3 && strcmp (argv
[1], "sections") == 0)
638 function
= cmd_sections
;
640 else if ((argc
== 3 || argc
== 4) && strcmp (argv
[1], "list") == 0)
645 else if ((argc
== 3 || argc
== 4) && strcmp (argv
[1], "details") == 0)
651 return cmd_help (FALSE
, argv
[1]);
653 (* function
) (argv
[2], section
, argc
> 3 ? argv
[3] : NULL
, details
);
658 /* vim:set foldmethod=marker: */