]>
Commit | Line | Data |
---|---|---|
0140c397 KZ |
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> | |
0140c397 | 13 | #include <stdlib.h> |
0140c397 | 14 | #include <getopt.h> |
0140c397 KZ |
15 | |
16 | #include "uuid.h" | |
17 | #include "nls.h" | |
0379a55d | 18 | #include "c.h" |
c05a80ca | 19 | #include "closestream.h" |
0140c397 | 20 | |
86be6a32 | 21 | static void __attribute__((__noreturn__)) usage(void) |
0140c397 | 22 | { |
86be6a32 | 23 | FILE *out = stdout; |
db433bf7 | 24 | fputs(USAGE_HEADER, out); |
44697763 KZ |
25 | fprintf(out, |
26 | _(" %s [options]\n"), program_invocation_short_name); | |
0379a55d | 27 | |
451dbcfa BS |
28 | fputs(USAGE_SEPARATOR, out); |
29 | fputs(_("Create a new UUID value.\n"), out); | |
30 | ||
db433bf7 | 31 | fputs(USAGE_OPTIONS, out); |
c6f1ec68 PP |
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 | fputs(_(" -N, --name name generate hash-based uuid from this name\n"), out); | |
36 | fputs(_(" -m, --md5 generate md5 hash\n"), out); | |
37 | fputs(_(" -s, --sha1 generate sha1 hash\n"), out); | |
38 | fputs(_(" -x, --hex interpret name as hex string\n"), out); | |
504c03ec | 39 | fputs(USAGE_SEPARATOR, out); |
f45f3ec3 RM |
40 | printf(USAGE_HELP_OPTIONS(18)); |
41 | printf(USAGE_MAN_TAIL("uuidgen(1)")); | |
86be6a32 | 42 | exit(EXIT_SUCCESS); |
0140c397 KZ |
43 | } |
44 | ||
c6f1ec68 PP |
45 | static char *unhex(const char *value, size_t *valuelen) |
46 | { | |
47 | char c, *value2; | |
48 | unsigned n, x; | |
49 | ||
50 | if (*valuelen % 2 != 0) { | |
51 | badstring: | |
52 | fprintf(stderr, "%s: not a valid hex string\n", program_invocation_short_name); | |
53 | errtryhelp(EXIT_FAILURE); | |
54 | } | |
55 | ||
56 | value2 = malloc(*valuelen / 2 + 1); | |
57 | ||
58 | for (x = n = 0; n < *valuelen; n++) { | |
59 | c = value[n]; | |
60 | if ('0' <= c && c <= '9') | |
61 | x += c - '0'; | |
62 | else if (('a' <= c && c <= 'f') || ('A' <= c && c <= 'F')) | |
63 | x += (c - 'A' + 10) & 0xf; | |
64 | else | |
65 | goto badstring; | |
66 | ||
67 | if (n % 2 == 0) | |
68 | x *= 16; | |
69 | else { | |
70 | value2[n / 2] = x; | |
71 | x = 0; | |
72 | } | |
73 | } | |
74 | value2[n / 2] = '\0'; | |
75 | ||
76 | *valuelen = (n / 2); | |
77 | ||
78 | return value2; | |
79 | } | |
80 | ||
0140c397 KZ |
81 | int |
82 | main (int argc, char *argv[]) | |
83 | { | |
84 | int c; | |
c6f1ec68 | 85 | int do_type = 0, is_hex = 0; |
b443c177 | 86 | char str[UUID_STR_LEN]; |
c6f1ec68 PP |
87 | char *namespace = NULL, *name = NULL; |
88 | size_t namelen = 0; | |
89 | uuid_t ns, uu; | |
0140c397 | 90 | |
0379a55d | 91 | static const struct option longopts[] = { |
71383195 | 92 | {"random", no_argument, NULL, 'r'}, |
0379a55d SK |
93 | {"time", no_argument, NULL, 't'}, |
94 | {"version", no_argument, NULL, 'V'}, | |
95 | {"help", no_argument, NULL, 'h'}, | |
c6f1ec68 PP |
96 | {"namespace", required_argument, NULL, 'n'}, |
97 | {"name", required_argument, NULL, 'N'}, | |
98 | {"md5", no_argument, NULL, 'm'}, | |
99 | {"sha1", no_argument, NULL, 's'}, | |
100 | {"hex", no_argument, NULL, 'x'}, | |
0379a55d SK |
101 | {NULL, 0, NULL, 0} |
102 | }; | |
103 | ||
0140c397 KZ |
104 | setlocale(LC_ALL, ""); |
105 | bindtextdomain(PACKAGE, LOCALEDIR); | |
106 | textdomain(PACKAGE); | |
c05a80ca | 107 | atexit(close_stdout); |
0140c397 | 108 | |
c6f1ec68 | 109 | while ((c = getopt_long(argc, argv, "rtVhn:N:msx", longopts, NULL)) != -1) |
0140c397 KZ |
110 | switch (c) { |
111 | case 't': | |
6328799d | 112 | do_type = UUID_TYPE_DCE_TIME; |
0140c397 KZ |
113 | break; |
114 | case 'r': | |
6328799d | 115 | do_type = UUID_TYPE_DCE_RANDOM; |
0140c397 | 116 | break; |
0379a55d | 117 | case 'V': |
e421313d | 118 | printf(UTIL_LINUX_VERSION); |
0379a55d | 119 | return EXIT_SUCCESS; |
c6f1ec68 PP |
120 | case 'n': |
121 | namespace = optarg; | |
122 | break; | |
123 | case 'N': | |
124 | name = optarg; | |
125 | break; | |
126 | case 'm': | |
127 | do_type = UUID_TYPE_DCE_MD5; | |
128 | break; | |
129 | case 's': | |
130 | do_type = UUID_TYPE_DCE_SHA1; | |
131 | break; | |
132 | case 'x': | |
133 | is_hex = 1; | |
134 | break; | |
0379a55d | 135 | case 'h': |
86be6a32 | 136 | usage(); |
0140c397 | 137 | default: |
677ec86c | 138 | errtryhelp(EXIT_FAILURE); |
0140c397 KZ |
139 | } |
140 | ||
c6f1ec68 PP |
141 | if (namespace) { |
142 | if (!name) { | |
143 | fprintf(stderr, "%s: --namespace requires --name argument\n", program_invocation_short_name); | |
144 | errtryhelp(EXIT_FAILURE); | |
145 | } | |
146 | if (do_type != UUID_TYPE_DCE_MD5 && do_type != UUID_TYPE_DCE_SHA1) { | |
147 | fprintf(stderr, "%s: --namespace requires --md5 or --sha1\n", program_invocation_short_name); | |
148 | errtryhelp(EXIT_FAILURE); | |
149 | } | |
150 | } else { | |
151 | if (name) { | |
152 | fprintf(stderr, "%s: --name requires --namespace argument\n", program_invocation_short_name); | |
153 | errtryhelp(EXIT_FAILURE); | |
154 | } | |
155 | if (do_type == UUID_TYPE_DCE_MD5 || do_type == UUID_TYPE_DCE_SHA1) { | |
156 | fprintf(stderr, "%s: --md5 or --sha1 require --namespace\n", program_invocation_short_name); | |
157 | errtryhelp(EXIT_FAILURE); | |
158 | } | |
159 | } | |
160 | ||
161 | if (name) { | |
162 | namelen = strlen(name); | |
163 | if (is_hex) | |
164 | name = unhex(name, &namelen); | |
165 | } | |
166 | ||
0140c397 | 167 | switch (do_type) { |
6328799d | 168 | case UUID_TYPE_DCE_TIME: |
0140c397 KZ |
169 | uuid_generate_time(uu); |
170 | break; | |
6328799d | 171 | case UUID_TYPE_DCE_RANDOM: |
0140c397 KZ |
172 | uuid_generate_random(uu); |
173 | break; | |
c6f1ec68 PP |
174 | case UUID_TYPE_DCE_MD5: |
175 | case UUID_TYPE_DCE_SHA1: | |
176 | if (namespace[0] == '@' && namespace[1] != '\0') { | |
177 | const uuid_t *uuidptr; | |
178 | ||
179 | uuidptr = uuid_get_template(&namespace[1]); | |
180 | if (uuidptr == NULL) { | |
181 | fprintf(stderr, "%s: unknown namespace alias '%s'\n", program_invocation_short_name, namespace); | |
182 | errtryhelp(EXIT_FAILURE); | |
183 | } | |
184 | memcpy(ns, *uuidptr, sizeof(ns)); | |
185 | } else { | |
186 | if (uuid_parse(namespace, ns) != 0) { | |
187 | fprintf(stderr, "%s: invalid uuid for namespace '%s'\n", program_invocation_short_name, namespace); | |
188 | errtryhelp(EXIT_FAILURE); | |
189 | } | |
190 | } | |
191 | if (do_type == UUID_TYPE_DCE_MD5) | |
192 | uuid_generate_md5(uu, ns, name, namelen); | |
193 | else | |
194 | uuid_generate_sha1(uu, ns, name, namelen); | |
195 | break; | |
0140c397 KZ |
196 | default: |
197 | uuid_generate(uu); | |
198 | break; | |
199 | } | |
200 | ||
201 | uuid_unparse(uu, str); | |
202 | ||
203 | printf("%s\n", str); | |
204 | ||
c6f1ec68 PP |
205 | if (is_hex) |
206 | free(name); | |
207 | ||
0379a55d | 208 | return EXIT_SUCCESS; |
0140c397 | 209 | } |