chiark / gitweb /
path: add new "systemd-path" utility for querying paths described in file-hierarchy(7)
[elogind.git] / src / path / path.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2014 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <stdio.h>
23 #include <getopt.h>
24 #include <error.h>
25 #include <errno.h>
26 #include <unistd.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include "sd-path.h"
31 #include "build.h"
32 #include "macro.h"
33 #include "util.h"
34 #include "log.h"
35
36 static const char *arg_suffix = NULL;
37
38 static const char* const path_table[_SD_PATH_MAX] = {
39         [SD_PATH_TEMPORARY] = "temporary",
40         [SD_PATH_TEMPORARY_LARGE] = "temporary-large",
41         [SD_PATH_SYSTEM_BINARIES] = "system-binaries",
42         [SD_PATH_SYSTEM_INCLUDE] = "system-include",
43         [SD_PATH_SYSTEM_LIBRARY_PRIVATE] = "system-library-private",
44         [SD_PATH_SYSTEM_LIBRARY_ARCH] = "system-library-arch",
45         [SD_PATH_SYSTEM_SHARED] = "system-shared",
46         [SD_PATH_SYSTEM_CONFIGURATION_FACTORY] = "system-configuration-factory",
47         [SD_PATH_SYSTEM_STATE_FACTORY] = "system-state-factory",
48         [SD_PATH_SYSTEM_CONFIGURATION] = "system-configuration",
49         [SD_PATH_SYSTEM_RUNTIME] = "system-runtime",
50         [SD_PATH_SYSTEM_RUNTIME_LOGS] = "system-runtime-logs",
51         [SD_PATH_SYSTEM_STATE_PRIVATE] = "system-state-private",
52         [SD_PATH_SYSTEM_STATE_LOGS] = "system-state-logs",
53         [SD_PATH_SYSTEM_STATE_CACHE] = "system-state-cache",
54         [SD_PATH_SYSTEM_STATE_SPOOL] = "system-state-spool",
55         [SD_PATH_USER_BINARIES] = "user-binaries",
56         [SD_PATH_USER_LIBRARY_PRIVATE] = "user-library-private",
57         [SD_PATH_USER_LIBRARY_ARCH] = "user-library-arch",
58         [SD_PATH_USER_SHARED] = "user-shared",
59         [SD_PATH_USER_CONFIGURATION] = "user-configuration",
60         [SD_PATH_USER_RUNTIME] = "user-runtime",
61         [SD_PATH_USER_STATE_CACHE] = "user-state-cache",
62         [SD_PATH_USER] = "user",
63         [SD_PATH_USER_DOCUMENTS] = "user-documents",
64         [SD_PATH_USER_MUSIC] = "user-music",
65         [SD_PATH_USER_PICTURES] = "user-pictures",
66         [SD_PATH_USER_VIDEOS] = "user-videos",
67         [SD_PATH_USER_DOWNLOAD] = "user-download",
68         [SD_PATH_USER_PUBLIC] = "user-public",
69         [SD_PATH_USER_TEMPLATES] = "user-templates",
70         [SD_PATH_USER_DESKTOP] = "user-desktop",
71         [SD_PATH_SEARCH_BINARIES] = "search-binaries",
72         [SD_PATH_SEARCH_LIBRARY_PRIVATE] = "search-library-private",
73         [SD_PATH_SEARCH_LIBRARY_ARCH] = "search-library-arch",
74         [SD_PATH_SEARCH_SHARED] = "search-shared",
75         [SD_PATH_SEARCH_CONFIGURATION_FACTORY] = "search-configuration-factory",
76         [SD_PATH_SEARCH_STATE_FACTORY] = "search-state-factory",
77         [SD_PATH_SEARCH_CONFIGURATION] = "search-configuration",
78 };
79
80 static int help(void) {
81
82         printf("%s [OPTIONS...] [NAME...]\n\n"
83                "Show system and user paths.\n\n"
84                "  -h --help             Show this help\n"
85                "     --version          Show package version\n"
86                "     --suffix=SUFFIX    Suffix to append to paths\n",
87                program_invocation_short_name);
88
89         return 0;
90 }
91
92 static int list_homes(void) {
93         uint64_t i = 0;
94         int r = 0;
95
96         for (i = 0; i < ELEMENTSOF(path_table); i++) {
97                 _cleanup_free_ char *p = NULL;
98                 int q;
99
100                 q = sd_path_home(i, arg_suffix, &p);
101                 if (q == -ENXIO)
102                         continue;
103                 if (q < 0) {
104                         log_error("Failed to query %s: %s", path_table[i], strerror(-r));
105                         r = q;
106                         continue;
107                 }
108
109                 printf("%s: %s\n", path_table[i], p);
110         }
111
112         return r;
113 }
114
115 static int print_home(const char *n) {
116         uint64_t i = 0;
117         int r;
118
119         for (i = 0; i < ELEMENTSOF(path_table); i++) {
120                 if (streq(path_table[i], n)) {
121                         _cleanup_free_ char *p = NULL;
122
123                         r = sd_path_home(i, arg_suffix, &p);
124                         if (r < 0) {
125                                 log_error("Failed to query %s: %s", n, strerror(-r));
126                                 return r;
127                         }
128
129                         printf("%s\n", p);
130                         return 0;
131                 }
132         }
133
134         log_error("Path %s not known.", n);
135         return -ENOTSUP;
136 }
137
138 static int parse_argv(int argc, char *argv[]) {
139
140         enum {
141                 ARG_VERSION = 0x100,
142                 ARG_SUFFIX,
143         };
144
145         static const struct option options[] = {
146                 { "help",      no_argument,       NULL, 'h'           },
147                 { "version",   no_argument,       NULL, ARG_VERSION   },
148                 { "suffix",    required_argument, NULL, ARG_SUFFIX    },
149                 {}
150         };
151
152         int c;
153
154         assert(argc >= 0);
155         assert(argv);
156
157         while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) {
158
159                 switch (c) {
160
161                 case 'h':
162                         return help();
163
164                 case ARG_VERSION:
165                         puts(PACKAGE_STRING);
166                         puts(SYSTEMD_FEATURES);
167                         return 0;
168
169                 case ARG_SUFFIX:
170                         arg_suffix = optarg;
171                         break;
172
173                 case '?':
174                         return -EINVAL;
175
176                 default:
177                         assert_not_reached("Unhandled option");
178                 }
179         }
180
181         return 1;
182 }
183
184 int main(int argc, char* argv[]) {
185         int r;
186
187         log_parse_environment();
188         log_open();
189
190         r = parse_argv(argc, argv);
191         if (r <= 0)
192                 goto finish;
193
194         if (argc > optind) {
195                 int i, q;
196
197                 for (i = optind; i < argc; i++) {
198                         q = print_home(argv[i]);
199                         if (q < 0)
200                                 r = q;
201                 }
202         } else
203                 r = list_homes();
204
205
206 finish:
207         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
208 }