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>
44 #include "glib/glib-private.h"
47 /* GResource functions {{{1 */
49 get_resource (const gchar
*file
)
58 if (g_file_get_contents (file
, &content
, &size
, NULL
))
60 data
= g_bytes_new_take (content
, size
);
61 resource
= g_resource_new_from_data (data
, NULL
);
69 list_resource (GResource
*resource
,
83 children
= g_resource_enumerate_children (resource
, path
, 0, &error
);
86 g_printerr ("%s\n", error
->message
);
90 for (i
= 0; children
[i
]; i
++)
92 child
= g_strconcat (path
, children
[i
], NULL
);
94 len
= MIN (strlen (child
), strlen (prefix
));
95 if (strncmp (child
, prefix
, len
) != 0)
98 if (g_resource_get_info (resource
, child
, 0, &size
, &flags
, NULL
))
101 g_print ("%s%s%6"G_GSIZE_FORMAT
" %s %s\n", section
, section
[0] ? " " : "", size
, flags
& G_RESOURCE_FLAGS_COMPRESSED
? "c" : "u", child
);
103 g_print ("%s\n", child
);
106 list_resource (resource
, child
, section
, prefix
, details
);
110 g_strfreev (children
);
114 extract_resource (GResource
*resource
,
119 bytes
= g_resource_lookup_data (resource
, path
, 0, NULL
);
125 data
= g_bytes_get_data (bytes
, &size
);
126 written
= fwrite (data
, 1, size
, stdout
);
128 g_printerr ("Data truncated\n");
129 g_bytes_unref (bytes
);
133 g_printerr ("Can't find resource path %s\n", path
);
137 /* Elf functions {{{1 */
142 get_elf (const gchar
*file
,
147 if (elf_version (EV_CURRENT
) == EV_NONE
)
150 *fd
= g_open (file
, O_RDONLY
, 0);
154 elf
= elf_begin (*fd
, ELF_C_READ
, NULL
);
158 if (elf_kind (elf
) != ELF_K_ELF
)
164 typedef gboolean (*SectionCallback
) (GElf_Shdr
*shdr
,
169 elf_foreach_resource_section (Elf
*elf
,
170 SectionCallback callback
,
173 size_t shstrndx
, shnum
;
176 GElf_Shdr
*shdr
, shdr_mem
;
177 const gchar
*section_name
;
179 elf_getshdrstrndx (elf
, &shstrndx
);
180 g_assert (shstrndx
>= 0);
182 elf_getshdrnum (elf
, &shnum
);
183 g_assert (shnum
>= 0);
185 for (scnidx
= 1; scnidx
< shnum
; scnidx
++)
187 scn
= elf_getscn (elf
, scnidx
);
191 shdr
= gelf_getshdr (scn
, &shdr_mem
);
195 if (shdr
->sh_type
!= SHT_PROGBITS
)
198 section_name
= elf_strptr (elf
, shstrndx
, shdr
->sh_name
);
199 if (section_name
== NULL
||
200 !g_str_has_prefix (section_name
, ".gresource."))
203 if (!callback (shdr
, section_name
+ strlen (".gresource."), data
))
209 resource_from_section (GElf_Shdr
*shdr
,
212 gsize page_size
, page_offset
;
218 page_size
= sysconf(_SC_PAGE_SIZE
);
219 page_offset
= shdr
->sh_offset
% page_size
;
220 contents
= mmap (NULL
, shdr
->sh_size
+ page_offset
,
221 PROT_READ
, MAP_PRIVATE
, fd
, shdr
->sh_offset
- page_offset
);
222 if (contents
!= MAP_FAILED
)
226 bytes
= g_bytes_new_static (contents
+ page_offset
, shdr
->sh_size
);
227 resource
= g_resource_new_from_data (bytes
, NULL
);
228 g_bytes_unref (bytes
);
232 g_printerr ("Can't mmap resource section");
241 const gchar
*section
;
248 list_resources_cb (GElf_Shdr
*shdr
,
249 const gchar
*section
,
252 CallbackData
*d
= data
;
255 if (d
->section
&& strcmp (section
, d
->section
) != 0)
260 resource
= resource_from_section (shdr
, d
->fd
);
261 list_resource (resource
, "/",
262 d
->section
? "" : section
,
265 g_resource_unref (resource
);
274 elf_list_resources (Elf
*elf
,
276 const gchar
*section
,
283 data
.section
= section
;
285 data
.details
= details
;
288 elf_foreach_resource_section (elf
, list_resources_cb
, &data
);
291 g_printerr ("Can't find resource section %s\n", section
);
295 extract_resource_cb (GElf_Shdr
*shdr
,
296 const gchar
*section
,
299 CallbackData
*d
= data
;
302 if (d
->section
&& strcmp (section
, d
->section
) != 0)
307 resource
= resource_from_section (shdr
, d
->fd
);
308 extract_resource (resource
, d
->path
);
309 g_resource_unref (resource
);
315 elf_extract_resource (Elf
*elf
,
317 const gchar
*section
,
323 data
.section
= section
;
327 elf_foreach_resource_section (elf
, extract_resource_cb
, &data
);
330 g_printerr ("Can't find resource section %s\n", section
);
334 print_section_name (GElf_Shdr
*shdr
,
338 g_print ("%s\n", name
);
342 #endif /* HAVE_LIBELF */
344 /* Toplevel commands {{{1 */
347 cmd_sections (const gchar
*file
,
348 const gchar
*section
,
359 if ((elf
= get_elf (file
, &fd
)))
361 elf_foreach_resource_section (elf
, print_section_name
, NULL
);
369 if ((resource
= get_resource (file
)))
372 g_resource_unref (resource
);
376 g_printerr ("Don't know how to handle %s\n", file
);
378 g_printerr ("gresource is built without elf support\n");
384 cmd_list (const gchar
*file
,
385 const gchar
*section
,
396 if ((elf
= get_elf (file
, &fd
)))
398 elf_list_resources (elf
, fd
, section
, path
? path
: "", details
);
406 if ((resource
= get_resource (file
)))
408 list_resource (resource
, "/", "", path
? path
: "", details
);
409 g_resource_unref (resource
);
413 g_printerr ("Don't know how to handle %s\n", file
);
415 g_printerr ("gresource is built without elf support\n");
421 cmd_extract (const gchar
*file
,
422 const gchar
*section
,
433 if ((elf
= get_elf (file
, &fd
)))
435 elf_extract_resource (elf
, fd
, section
, path
);
443 if ((resource
= get_resource (file
)))
445 extract_resource (resource
, path
);
446 g_resource_unref (resource
);
450 g_printerr ("Don't know how to handle %s\n", file
);
452 g_printerr ("gresource is built without elf support\n");
458 cmd_help (gboolean requested
,
459 const gchar
*command
)
461 const gchar
*description
;
462 const gchar
*synopsis
;
468 string
= g_string_new (NULL
);
473 else if (strcmp (command
, "help") == 0)
475 description
= _("Print help");
476 synopsis
= _("[COMMAND]");
479 else if (strcmp (command
, "sections") == 0)
481 description
= _("List sections containing resources in an elf FILE");
482 synopsis
= _("FILE");
485 else if (strcmp (command
, "list") == 0)
487 description
= _("List resources\n"
488 "If SECTION is given, only list resources in this section\n"
489 "If PATH is given, only list matching resources");
490 synopsis
= _("FILE [PATH]");
491 option
= g_strdup_printf ("[--section %s]", _("SECTION"));
494 else if (strcmp (command
, "details") == 0)
496 description
= _("List resources with details\n"
497 "If SECTION is given, only list resources in this section\n"
498 "If PATH is given, only list matching resources\n"
499 "Details include the section, size and compression");
500 synopsis
= _("FILE [PATH]");
501 option
= g_strdup_printf ("[--section %s]", _("SECTION"));
504 else if (strcmp (command
, "extract") == 0)
506 description
= _("Extract a resource file to stdout");
507 synopsis
= _("FILE PATH");
508 option
= g_strdup_printf ("[--section %s]", _("SECTION"));
513 g_string_printf (string
, _("Unknown command %s\n\n"), command
);
520 g_string_append (string
,
522 " gresource [--section SECTION] COMMAND [ARGS...]\n"
525 " help Show this information\n"
526 " sections List resource sections\n"
527 " list List resources\n"
528 " details List resources with details\n"
529 " extract Extract a resource\n"
531 "Use 'gresource help COMMAND' to get detailed help.\n\n"));
535 g_string_append_printf (string
, _("Usage:\n gresource %s%s%s %s\n\n%s\n\n"),
536 option
? option
: "", option
? " " : "", command
, synopsis
[0] ? synopsis
: "", description
);
538 g_string_append (string
, _("Arguments:\n"));
541 g_string_append (string
,
542 _(" SECTION An (optional) elf section name\n"));
544 if (strstr (synopsis
, _("[COMMAND]")))
545 g_string_append (string
,
546 _(" COMMAND The (optional) command to explain\n"));
548 if (strstr (synopsis
, _("FILE")))
550 if (strcmp (command
, "sections") == 0)
551 g_string_append (string
,
552 _(" FILE An elf file (a binary or a shared library)\n"));
554 g_string_append (string
,
555 _(" FILE An elf file (a binary or a shared library)\n"
556 " or a compiled resource file\n"));
559 if (strstr (synopsis
, _("[PATH]")))
560 g_string_append (string
,
561 _(" PATH An (optional) resource path (may be partial)\n"));
562 else if (strstr (synopsis
, _("PATH")))
563 g_string_append (string
,
564 _(" PATH A resource path\n"));
566 g_string_append (string
, "\n");
570 g_print ("%s", string
->str
);
572 g_printerr ("%s\n", string
->str
);
575 g_string_free (string
, TRUE
);
577 return requested
? 0 : 1;
583 main (int argc
, char *argv
[])
585 gchar
*section
= NULL
;
586 gboolean details
= FALSE
;
587 void (* function
) (const gchar
*, const gchar
*, const gchar
*, gboolean
);
593 setlocale (LC_ALL
, "");
594 textdomain (GETTEXT_PACKAGE
);
597 tmp
= _glib_get_locale_dir ();
598 bindtextdomain (GETTEXT_PACKAGE
, tmp
);
601 bindtextdomain (GETTEXT_PACKAGE
, GLIB_LOCALE_DIR
);
604 #ifdef HAVE_BIND_TEXTDOMAIN_CODESET
605 bind_textdomain_codeset (GETTEXT_PACKAGE
, "UTF-8");
609 return cmd_help (FALSE
, NULL
);
611 if (argc
> 3 && strcmp (argv
[1], "--section") == 0)
618 if (strcmp (argv
[1], "help") == 0)
619 return cmd_help (TRUE
, argv
[2]);
621 else if (argc
== 4 && strcmp (argv
[1], "extract") == 0)
622 function
= cmd_extract
;
624 else if (argc
== 3 && strcmp (argv
[1], "sections") == 0)
625 function
= cmd_sections
;
627 else if ((argc
== 3 || argc
== 4) && strcmp (argv
[1], "list") == 0)
632 else if ((argc
== 3 || argc
== 4) && strcmp (argv
[1], "details") == 0)
638 return cmd_help (FALSE
, argv
[1]);
640 (* function
) (argv
[2], section
, argc
> 3 ? argv
[3] : NULL
, details
);
645 /* vim:set foldmethod=marker: */