]> git.ipfire.org Git - thirdparty/util-linux.git/blob - misc-utils/uuidgen.c
uuidgen: give hint in usage() what uuid namepaces can be used
[thirdparty/util-linux.git] / misc-utils / uuidgen.c
1 /*
2 * gen_uuid.c --- generate a DCE-compatible uuid
3 *
4 * Copyright (C) 1999, Andreas Dilger and Theodore Ts'o
5 *
6 * %Begin-Header%
7 * This file may be redistributed under the terms of the GNU Public
8 * License.
9 * %End-Header%
10 */
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <getopt.h>
15
16 #include "uuid.h"
17 #include "nls.h"
18 #include "c.h"
19 #include "closestream.h"
20
21 static void __attribute__((__noreturn__)) usage(void)
22 {
23 FILE *out = stdout;
24 fputs(USAGE_HEADER, out);
25 fprintf(out,
26 _(" %s [options]\n"), program_invocation_short_name);
27
28 fputs(USAGE_SEPARATOR, out);
29 fputs(_("Create a new UUID value.\n"), out);
30
31 fputs(USAGE_OPTIONS, out);
32 fputs(_(" -r, --random generate random-based uuid\n"), out);
33 fputs(_(" -t, --time generate time-based uuid\n"), out);
34 fputs(_(" -n, --namespace ns generate hash-based uuid in this namespace\n"), out);
35 printf(_(" available namespaces: %s\n"), "@dns @url @oid @x500");
36 fputs(_(" -N, --name name generate hash-based uuid from this name\n"), out);
37 fputs(_(" -m, --md5 generate md5 hash\n"), out);
38 fputs(_(" -s, --sha1 generate sha1 hash\n"), out);
39 fputs(_(" -x, --hex interpret name as hex string\n"), out);
40 fputs(USAGE_SEPARATOR, out);
41 printf(USAGE_HELP_OPTIONS(21));
42 printf(USAGE_MAN_TAIL("uuidgen(1)"));
43 exit(EXIT_SUCCESS);
44 }
45
46 static char *unhex(const char *value, size_t *valuelen)
47 {
48 char c, *value2;
49 unsigned n, x;
50
51 if (*valuelen % 2 != 0) {
52 badstring:
53 warnx(_("not a valid hex string"));
54 errtryhelp(EXIT_FAILURE);
55 }
56
57 value2 = malloc(*valuelen / 2 + 1);
58
59 for (x = n = 0; n < *valuelen; n++) {
60 c = value[n];
61 if ('0' <= c && c <= '9')
62 x += c - '0';
63 else if (('a' <= c && c <= 'f') || ('A' <= c && c <= 'F'))
64 x += (c - 'A' + 10) & 0xf;
65 else
66 goto badstring;
67
68 if (n % 2 == 0)
69 x *= 16;
70 else {
71 value2[n / 2] = x;
72 x = 0;
73 }
74 }
75 value2[n / 2] = '\0';
76
77 *valuelen = (n / 2);
78
79 return value2;
80 }
81
82 int
83 main (int argc, char *argv[])
84 {
85 int c;
86 int do_type = 0, is_hex = 0;
87 char str[UUID_STR_LEN];
88 char *namespace = NULL, *name = NULL;
89 size_t namelen = 0;
90 uuid_t ns, uu;
91
92 static const struct option longopts[] = {
93 {"random", no_argument, NULL, 'r'},
94 {"time", no_argument, NULL, 't'},
95 {"version", no_argument, NULL, 'V'},
96 {"help", no_argument, NULL, 'h'},
97 {"namespace", required_argument, NULL, 'n'},
98 {"name", required_argument, NULL, 'N'},
99 {"md5", no_argument, NULL, 'm'},
100 {"sha1", no_argument, NULL, 's'},
101 {"hex", no_argument, NULL, 'x'},
102 {NULL, 0, NULL, 0}
103 };
104
105 setlocale(LC_ALL, "");
106 bindtextdomain(PACKAGE, LOCALEDIR);
107 textdomain(PACKAGE);
108 close_stdout_atexit();
109
110 while ((c = getopt_long(argc, argv, "rtVhn:N:msx", longopts, NULL)) != -1)
111 switch (c) {
112 case 't':
113 do_type = UUID_TYPE_DCE_TIME;
114 break;
115 case 'r':
116 do_type = UUID_TYPE_DCE_RANDOM;
117 break;
118 case 'n':
119 namespace = optarg;
120 break;
121 case 'N':
122 name = optarg;
123 break;
124 case 'm':
125 do_type = UUID_TYPE_DCE_MD5;
126 break;
127 case 's':
128 do_type = UUID_TYPE_DCE_SHA1;
129 break;
130 case 'x':
131 is_hex = 1;
132 break;
133
134 case 'h':
135 usage();
136 case 'V':
137 print_version(EXIT_SUCCESS);
138 default:
139 errtryhelp(EXIT_FAILURE);
140 }
141
142 if (namespace) {
143 if (!name) {
144 warnx(_("--namespace requires --name argument"));
145 errtryhelp(EXIT_FAILURE);
146 }
147 if (do_type != UUID_TYPE_DCE_MD5 && do_type != UUID_TYPE_DCE_SHA1) {
148 warnx(_("--namespace requires --md5 or --sha1"));
149 errtryhelp(EXIT_FAILURE);
150 }
151 } else {
152 if (name) {
153 warnx(_("--name requires --namespace argument"));
154 errtryhelp(EXIT_FAILURE);
155 }
156 if (do_type == UUID_TYPE_DCE_MD5 || do_type == UUID_TYPE_DCE_SHA1) {
157 warnx(_("--md5 or --sha1 requires --namespace argument"));
158 errtryhelp(EXIT_FAILURE);
159 }
160 }
161
162 if (name) {
163 namelen = strlen(name);
164 if (is_hex)
165 name = unhex(name, &namelen);
166 }
167
168 switch (do_type) {
169 case UUID_TYPE_DCE_TIME:
170 uuid_generate_time(uu);
171 break;
172 case UUID_TYPE_DCE_RANDOM:
173 uuid_generate_random(uu);
174 break;
175 case UUID_TYPE_DCE_MD5:
176 case UUID_TYPE_DCE_SHA1:
177 if (namespace[0] == '@' && namespace[1] != '\0') {
178 const uuid_t *uuidptr;
179
180 uuidptr = uuid_get_template(&namespace[1]);
181 if (uuidptr == NULL) {
182 warnx(_("unknown namespace alias: '%s'"), namespace);
183 errtryhelp(EXIT_FAILURE);
184 }
185 memcpy(ns, *uuidptr, sizeof(ns));
186 } else {
187 if (uuid_parse(namespace, ns) != 0) {
188 warnx(_("invalid uuid for namespace: '%s'"), namespace);
189 errtryhelp(EXIT_FAILURE);
190 }
191 }
192 if (do_type == UUID_TYPE_DCE_MD5)
193 uuid_generate_md5(uu, ns, name, namelen);
194 else
195 uuid_generate_sha1(uu, ns, name, namelen);
196 break;
197 default:
198 uuid_generate(uu);
199 break;
200 }
201
202 uuid_unparse(uu, str);
203
204 printf("%s\n", str);
205
206 if (is_hex)
207 free(name);
208
209 return EXIT_SUCCESS;
210 }