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