2 * gen_uuid.c --- generate a DCE-compatible uuid
4 * Copyright (C) 1999, Andreas Dilger and Theodore Ts'o
7 * This file may be redistributed under the terms of the
8 * GNU General Public License.
19 #include "closestream.h"
24 static void __attribute__((__noreturn__
)) usage(void)
27 fputs(USAGE_HEADER
, out
);
29 _(" %s [options]\n"), program_invocation_short_name
);
31 fputs(USAGE_SEPARATOR
, out
);
32 fputs(_("Create a new UUID value.\n"), out
);
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(_(" -6, --time-v6 generate time-based v6 uuid\n"), out
);
44 fputs(_(" -7, --time-v7 generate time-based v7 uuid\n"), out
);
45 fputs(_(" -x, --hex interpret name as hex string\n"), out
);
46 fputs(USAGE_SEPARATOR
, out
);
47 fprintf(out
, USAGE_HELP_OPTIONS(21));
48 fprintf(out
, USAGE_MAN_TAIL("uuidgen(1)"));
52 static char *unhex(const char *value
, size_t *valuelen
)
57 if (*valuelen
% 2 != 0) {
59 warnx(_("not a valid hex string"));
60 errtryhelp(EXIT_FAILURE
);
63 value2
= xmalloc(*valuelen
/ 2 + 1);
65 for (x
= n
= 0; n
< *valuelen
; n
++) {
67 if ('0' <= c
&& c
<= '9')
69 else if (('a' <= c
&& c
<= 'f') || ('A' <= c
&& c
<= 'F'))
70 x
+= (c
- 'A' + 10) & 0xf;
89 main (int argc
, char *argv
[])
92 int do_type
= 0, is_hex
= 0;
93 char str
[UUID_STR_LEN
];
94 char *namespace = NULL
, *name
= NULL
;
97 unsigned int count
= 1, i
;
99 static const struct option longopts
[] = {
100 {"random", no_argument
, NULL
, 'r'},
101 {"time", no_argument
, NULL
, 't'},
102 {"version", no_argument
, NULL
, 'V'},
103 {"help", no_argument
, NULL
, 'h'},
104 {"namespace", required_argument
, NULL
, 'n'},
105 {"name", required_argument
, NULL
, 'N'},
106 {"md5", no_argument
, NULL
, 'm'},
107 {"count", required_argument
, NULL
, 'C'},
108 {"sha1", no_argument
, NULL
, 's'},
109 {"time-v6", no_argument
, NULL
, '6'},
110 {"time-v7", no_argument
, NULL
, '7'},
111 {"hex", no_argument
, NULL
, 'x'},
115 static const ul_excl_t excl
[] = {
116 { '6', '7', 'm', 'r', 's', 't' },
122 int excl_st
[ARRAY_SIZE(excl
)] = UL_EXCL_STATUS_INIT
;
124 setlocale(LC_ALL
, "");
125 bindtextdomain(PACKAGE
, LOCALEDIR
);
127 close_stdout_atexit();
129 while ((c
= getopt_long(argc
, argv
, "C:rtVhn:N:msx67", longopts
, NULL
)) != -1) {
131 err_exclusive_options(c
, longopts
, excl
, excl_st
);
135 do_type
= UUID_TYPE_DCE_TIME
;
138 do_type
= UUID_TYPE_DCE_RANDOM
;
147 do_type
= UUID_TYPE_DCE_MD5
;
150 count
= strtou32_or_err(optarg
, _("invalid count argument"));
153 do_type
= UUID_TYPE_DCE_SHA1
;
159 do_type
= UUID_TYPE_DCE_TIME_V6
;
162 do_type
= UUID_TYPE_DCE_TIME_V7
;
168 print_version(EXIT_SUCCESS
);
170 errtryhelp(EXIT_FAILURE
);
176 warnx(_("--namespace requires --name argument"));
177 errtryhelp(EXIT_FAILURE
);
179 if (do_type
!= UUID_TYPE_DCE_MD5
&& do_type
!= UUID_TYPE_DCE_SHA1
) {
180 warnx(_("--namespace requires --md5 or --sha1"));
181 errtryhelp(EXIT_FAILURE
);
185 warnx(_("--name requires --namespace argument"));
186 errtryhelp(EXIT_FAILURE
);
188 if (do_type
== UUID_TYPE_DCE_MD5
|| do_type
== UUID_TYPE_DCE_SHA1
) {
189 warnx(_("--md5 or --sha1 requires --namespace argument"));
190 errtryhelp(EXIT_FAILURE
);
195 namelen
= strlen(name
);
197 name
= unhex(name
, &namelen
);
200 for (i
= 0; i
< count
; i
++) {
202 case UUID_TYPE_DCE_TIME
:
203 uuid_generate_time(uu
);
205 case UUID_TYPE_DCE_TIME_V6
:
206 uuid_generate_time_v6(uu
);
208 case UUID_TYPE_DCE_TIME_V7
:
209 uuid_generate_time_v7(uu
);
211 case UUID_TYPE_DCE_RANDOM
:
212 uuid_generate_random(uu
);
214 case UUID_TYPE_DCE_MD5
:
215 case UUID_TYPE_DCE_SHA1
:
216 if (namespace[0] == '@' && namespace[1] != '\0') {
217 const uuid_t
*uuidptr
;
219 uuidptr
= uuid_get_template(&namespace[1]);
220 if (uuidptr
== NULL
) {
221 warnx(_("unknown namespace alias: '%s'"), namespace);
222 errtryhelp(EXIT_FAILURE
);
224 memcpy(ns
, *uuidptr
, sizeof(ns
));
226 if (uuid_parse(namespace, ns
) != 0) {
227 warnx(_("invalid uuid for namespace: '%s'"), namespace);
228 errtryhelp(EXIT_FAILURE
);
231 if (do_type
== UUID_TYPE_DCE_MD5
)
232 uuid_generate_md5(uu
, ns
, name
, namelen
);
234 uuid_generate_sha1(uu
, ns
, name
, namelen
);
241 uuid_unparse(uu
, str
);