[gobject] set all properties before constructed()
[glib.git] / gio / gresource-tool.c
blob70c9ee656c2817621d7ea390fd95946cf61a7bc3
1 /*
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
22 #include "config.h"
24 #include <stdlib.h>
25 #include <stdio.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <fcntl.h>
30 #include <string.h>
31 #include <locale.h>
33 #ifdef HAVE_LIBELF
34 #include <libelf.h>
35 #include <gelf.h>
36 #include <sys/mman.h>
37 #endif
39 #include <gio/gio.h>
40 #include <glib/gstdio.h>
41 #include <gi18n.h>
43 /* GResource functions {{{1 */
44 static GResource *
45 get_resource (const gchar *file)
47 gchar *content;
48 gsize size;
49 GResource *resource;
50 GBytes *data;
52 resource = NULL;
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);
58 g_bytes_unref (data);
61 return resource;
64 static void
65 list_resource (GResource *resource,
66 const gchar *path,
67 const gchar *section,
68 const gchar *prefix,
69 gboolean details)
71 gchar **children;
72 gsize size;
73 guint32 flags;
74 gint i;
75 gchar *child;
76 GError *error = NULL;
77 gint len;
79 children = g_resource_enumerate_children (resource, path, 0, &error);
80 if (error)
82 g_printerr ("%s\n", error->message);
83 g_error_free (error);
84 return;
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)
92 continue;
94 if (g_resource_get_info (resource, child, 0, &size, &flags, NULL))
96 if (details)
97 g_print ("%s%s%6"G_GSIZE_FORMAT " %s %s\n", section, section[0] ? " " : "", size, flags & G_RESOURCE_FLAGS_COMPRESSED ? "c" : "u", child);
98 else
99 g_print ("%s\n", child);
101 else
102 list_resource (resource, child, section, prefix, details);
104 g_free (child);
106 g_strfreev (children);
109 static void
110 extract_resource (GResource *resource,
111 const gchar *path)
113 GBytes *bytes;
115 bytes = g_resource_lookup_data (resource, path, 0, NULL);
116 if (bytes != NULL)
118 gconstpointer data;
119 gsize size, written;
121 data = g_bytes_get_data (bytes, &size);
122 written = fwrite (data, 1, size, stdout);
123 if (written < size)
124 g_printerr ("Data truncated\n");
125 g_bytes_unref (bytes);
127 else
129 g_printerr ("Can't find resource path %s\n", path);
133 /* Elf functions {{{1 */
135 #ifdef HAVE_LIBELF
137 static Elf *
138 get_elf (const gchar *file,
139 gint *fd)
141 Elf *elf;
143 if (elf_version (EV_CURRENT) == EV_NONE )
144 return NULL;
146 *fd = g_open (file, O_RDONLY, 0);
147 if (*fd < 0)
148 return NULL;
150 elf = elf_begin (*fd, ELF_C_READ, NULL);
151 if (elf == NULL)
152 return NULL;
154 if (elf_kind (elf) != ELF_K_ELF)
155 return NULL;
157 return elf;
160 typedef gboolean (*SectionCallback) (GElf_Shdr *shdr,
161 const gchar *name,
162 gpointer data);
164 static void
165 elf_foreach_resource_section (Elf *elf,
166 SectionCallback callback,
167 gpointer data)
169 size_t shstrndx, shnum;
170 size_t scnidx;
171 Elf_Scn *scn;
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);
184 if (scn == NULL)
185 continue;
187 shdr = gelf_getshdr (scn, &shdr_mem);
188 if (shdr == NULL)
189 continue;
191 if (shdr->sh_type != SHT_PROGBITS)
192 continue;
194 section_name = elf_strptr (elf, shstrndx, shdr->sh_name);
195 if (section_name == NULL ||
196 !g_str_has_prefix (section_name, ".gresource."))
197 continue;
199 if (!callback (shdr, section_name + strlen (".gresource."), data))
200 break;
204 static GResource *
205 resource_from_section (GElf_Shdr *shdr,
206 int fd)
208 gsize page_size, page_offset;
209 char *contents;
210 GResource *resource;
212 resource = NULL;
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)
220 GBytes *bytes;
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);
226 else
228 g_printerr ("Can't mmap resource section");
231 return resource;
234 typedef struct
236 int fd;
237 const gchar *section;
238 const gchar *path;
239 gboolean details;
240 gboolean found;
241 } CallbackData;
243 static gboolean
244 list_resources_cb (GElf_Shdr *shdr,
245 const gchar *section,
246 gpointer data)
248 CallbackData *d = data;
249 GResource *resource;
251 if (d->section && strcmp (section, d->section) != 0)
252 return TRUE;
254 d->found = TRUE;
256 resource = resource_from_section (shdr, d->fd);
257 list_resource (resource, "/",
258 d->section ? "" : section,
259 d->path,
260 d->details);
261 g_resource_unref (resource);
263 if (d->section)
264 return FALSE;
266 return TRUE;
269 static void
270 elf_list_resources (Elf *elf,
271 int fd,
272 const gchar *section,
273 const gchar *path,
274 gboolean details)
276 CallbackData data;
278 data.fd = fd;
279 data.section = section;
280 data.path = path;
281 data.details = details;
282 data.found = FALSE;
284 elf_foreach_resource_section (elf, list_resources_cb, &data);
286 if (!data.found)
287 g_printerr ("Can't find resource section %s\n", section);
290 static gboolean
291 extract_resource_cb (GElf_Shdr *shdr,
292 const gchar *section,
293 gpointer data)
295 CallbackData *d = data;
296 GResource *resource;
298 if (d->section && strcmp (section, d->section) != 0)
299 return TRUE;
301 d->found = TRUE;
303 resource = resource_from_section (shdr, d->fd);
304 extract_resource (resource, d->path);
305 g_resource_unref (resource);
307 return FALSE;
310 static void
311 elf_extract_resource (Elf *elf,
312 int fd,
313 const gchar *section,
314 const gchar *path)
316 CallbackData data;
318 data.fd = fd;
319 data.section = section;
320 data.path = path;
321 data.found = FALSE;
323 elf_foreach_resource_section (elf, extract_resource_cb, &data);
325 if (!data.found)
326 g_printerr ("Can't find resource section %s\n", section);
329 static gboolean
330 print_section_name (GElf_Shdr *shdr,
331 const gchar *name,
332 gpointer data)
334 g_print ("%s\n", name);
335 return TRUE;
338 #endif /* HAVE_LIBELF */
340 /* Toplevel commands {{{1 */
342 static void
343 cmd_sections (const gchar *file,
344 const gchar *section,
345 const gchar *path,
346 gboolean details)
348 GResource *resource;
350 #ifdef HAVE_LIBELF
352 Elf *elf;
353 gint fd;
355 if ((elf = get_elf (file, &fd)))
357 elf_foreach_resource_section (elf, print_section_name, NULL);
358 elf_end (elf);
359 close (fd);
361 else
363 #endif
365 if ((resource = get_resource (file)))
367 /* No sections */
368 g_resource_unref (resource);
370 else
372 g_printerr ("Don't know how to handle %s\n", file);
373 #ifndef HAVE_LIBELF
374 g_printerr ("gresource is built without elf support\n");
375 #endif
379 static void
380 cmd_list (const gchar *file,
381 const gchar *section,
382 const gchar *path,
383 gboolean details)
385 GResource *resource;
387 #ifdef HAVE_LIBELF
389 Elf *elf;
390 int fd;
392 if ((elf = get_elf (file, &fd)))
394 elf_list_resources (elf, fd, section, path ? path : "", details);
395 elf_end (elf);
396 close (fd);
398 else
400 #endif
402 if ((resource = get_resource (file)))
404 list_resource (resource, "/", "", path ? path : "", details);
405 g_resource_unref (resource);
407 else
409 g_printerr ("Don't know how to handle %s\n", file);
410 #ifndef HAVE_LIBELF
411 g_printerr ("gresource is built without elf support\n");
412 #endif
416 static void
417 cmd_extract (const gchar *file,
418 const gchar *section,
419 const gchar *path,
420 gboolean details)
422 GResource *resource;
424 #ifdef HAVE_LIBELF
426 Elf *elf;
427 int fd;
429 if ((elf = get_elf (file, &fd)))
431 elf_extract_resource (elf, fd, section, path);
432 elf_end (elf);
433 close (fd);
435 else
437 #endif
439 if ((resource = get_resource (file)))
441 extract_resource (resource, path);
442 g_resource_unref (resource);
444 else
446 g_printerr ("Don't know how to handle %s\n", file);
447 #ifndef HAVE_LIBELF
448 g_printerr ("gresource is built without elf support\n");
449 #endif
453 static gint
454 cmd_help (gboolean requested,
455 const gchar *command)
457 const gchar *description;
458 const gchar *synopsis;
459 gchar *option;
460 GString *string;
462 option = NULL;
464 string = g_string_new (NULL);
466 if (command == 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"));
507 else
509 g_string_printf (string, _("Unknown command %s\n\n"), command);
510 requested = FALSE;
511 command = NULL;
514 if (command == NULL)
516 g_string_append (string,
517 _("Usage:\n"
518 " gresource [--section SECTION] COMMAND [ARGS...]\n"
519 "\n"
520 "Commands:\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"
526 "\n"
527 "Use 'gresource help COMMAND' to get detailed help.\n\n"));
529 else
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"));
536 if (option)
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"));
549 else
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");
565 if (requested)
566 g_print ("%s", string->str);
567 else
568 g_printerr ("%s\n", string->str);
570 g_free (option);
571 g_string_free (string, TRUE);
573 return requested ? 0 : 1;
576 /* main {{{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);
585 #ifdef G_OS_WIN32
586 extern gchar *_glib_get_locale_dir (void);
587 gchar *tmp;
588 #endif
590 setlocale (LC_ALL, "");
591 textdomain (GETTEXT_PACKAGE);
593 #ifdef G_OS_WIN32
594 tmp = _glib_get_locale_dir ();
595 bindtextdomain (GETTEXT_PACKAGE, tmp);
596 g_free (tmp);
597 #else
598 bindtextdomain (GETTEXT_PACKAGE, GLIB_LOCALE_DIR);
599 #endif
601 #ifdef HAVE_BIND_TEXTDOMAIN_CODESET
602 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
603 #endif
605 g_type_init ();
607 if (argc < 2)
608 return cmd_help (FALSE, NULL);
610 if (argc > 3 && strcmp (argv[1], "--section") == 0)
612 section = argv[2];
613 argv = argv + 2;
614 argc -= 2;
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)
628 function = cmd_list;
629 details = FALSE;
631 else if ((argc == 3 || argc == 4) && strcmp (argv[1], "details") == 0)
633 function = cmd_list;
634 details = TRUE;
636 else
637 return cmd_help (FALSE, argv[1]);
639 (* function) (argv[2], section, argc > 3 ? argv[3] : NULL, details);
641 return 0;
644 /* vim:set foldmethod=marker: */