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