Line data Source code
1 : /* Command-line frontend for retrieving ELF / DWARF / source files
2 : from the debuginfod.
3 : Copyright (C) 2019 Red Hat, Inc.
4 : This file is part of elfutils.
5 :
6 : This file is free software; you can redistribute it and/or modify
7 : it under the terms of the GNU General Public License as published by
8 : the Free Software Foundation; either version 3 of the License, or
9 : (at your option) any later version.
10 :
11 : elfutils is distributed in the hope that it will be useful, but
12 : WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : General Public License for more details.
15 :
16 : You should have received copies of the GNU General Public License and
17 : the GNU Lesser General Public License along with this program. If
18 : not, see <http://www.gnu.org/licenses/>. */
19 :
20 : #include "config.h"
21 : #include "printversion.h"
22 : #include "debuginfod.h"
23 : #include <errno.h>
24 : #include <stdio.h>
25 : #include <stdlib.h>
26 : #include <string.h>
27 : #include <argp.h>
28 :
29 :
30 : /* Name and version of program. */
31 : ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
32 :
33 : /* Bug report address. */
34 : ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
35 :
36 : /* Short description of program. */
37 : static const char doc[] = N_("Request debuginfo-related content "
38 : "from debuginfods listed in $" DEBUGINFOD_URLS_ENV_VAR ".");
39 :
40 : /* Strings for arguments in help texts. */
41 : static const char args_doc[] = N_("debuginfo BUILDID\n"
42 : "executable BUILDID\n"
43 : "source BUILDID /FILENAME");
44 :
45 : /* Definitions of arguments for argp functions. */
46 : static const struct argp_option options[] =
47 : {
48 : { "verbose", 'v', NULL, 0, "Increase verbosity.", 0 },
49 : { NULL, 0, NULL, 0, NULL, 0 }
50 : };
51 :
52 : /* debuginfod connection handle. */
53 : static debuginfod_client *client;
54 :
55 3 : int progressfn(debuginfod_client *c __attribute__((__unused__)),
56 : long a, long b)
57 : {
58 3 : fprintf (stderr, "Progress %ld / %ld\n", a, b);
59 3 : return 0;
60 : }
61 :
62 :
63 151 : static error_t parse_opt (int key, char *arg, struct argp_state *state)
64 : {
65 151 : (void) arg;
66 151 : (void) state;
67 151 : switch (key)
68 : {
69 1 : case 'v': debuginfod_set_progressfn (client, & progressfn); break;
70 : default: return ARGP_ERR_UNKNOWN;
71 : }
72 1 : return 0;
73 : }
74 :
75 :
76 : /* Data structure to communicate with argp functions. */
77 : static struct argp argp =
78 : {
79 : options, parse_opt, args_doc, doc, NULL, NULL, NULL
80 : };
81 :
82 :
83 :
84 : int
85 30 : main(int argc, char** argv)
86 : {
87 30 : client = debuginfod_begin ();
88 30 : if (client == NULL)
89 : {
90 0 : fprintf(stderr, "Couldn't create debuginfod client context\n");
91 0 : return 1;
92 : }
93 :
94 30 : int remaining;
95 30 : (void) argp_parse (&argp, argc, argv, ARGP_IN_ORDER|ARGP_NO_ARGS, &remaining, NULL);
96 :
97 30 : if (argc < 2 || remaining+1 == argc) /* no arguments or at least two non-option words */
98 : {
99 0 : argp_help (&argp, stderr, ARGP_HELP_USAGE, argv[0]);
100 0 : return 1;
101 : }
102 :
103 30 : int rc;
104 30 : char *cache_name;
105 :
106 : /* Check whether FILETYPE is valid and call the appropriate
107 : debuginfod_find_* function. If FILETYPE is "source"
108 : then ensure a FILENAME was also supplied as an argument. */
109 30 : if (strcmp(argv[remaining], "debuginfo") == 0)
110 24 : rc = debuginfod_find_debuginfo(client,
111 12 : (unsigned char *)argv[remaining+1], 0,
112 : &cache_name);
113 18 : else if (strcmp(argv[remaining], "executable") == 0)
114 20 : rc = debuginfod_find_executable(client,
115 10 : (unsigned char *)argv[remaining+1], 0,
116 : &cache_name);
117 8 : else if (strcmp(argv[remaining], "source") == 0)
118 : {
119 8 : if (remaining+2 == argc || argv[3][0] != '/')
120 : {
121 0 : fprintf(stderr, "If FILETYPE is \"source\" then absolute /FILENAME must be given\n");
122 0 : return 1;
123 : }
124 16 : rc = debuginfod_find_source(client, (unsigned char *)argv[remaining+1],
125 8 : 0, argv[remaining+2], &cache_name);
126 : }
127 : else
128 : {
129 0 : argp_help (&argp, stderr, ARGP_HELP_USAGE, argv[0]);
130 0 : return 1;
131 : }
132 :
133 30 : if (rc < 0)
134 : {
135 3 : fprintf(stderr, "Server query failed: %s\n", strerror(-rc));
136 3 : return 1;
137 : }
138 :
139 27 : printf("%s\n", cache_name);
140 :
141 27 : free (cache_name);
142 27 : debuginfod_end (client);
143 :
144 27 : return 0;
145 : }
|