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 GNU Public
19 #include "closestream.h"
21 static void __attribute__((__noreturn__
)) usage(void)
24 fputs(USAGE_HEADER
, out
);
26 _(" %s [options]\n"), program_invocation_short_name
);
28 fputs(USAGE_SEPARATOR
, out
);
29 fputs(_("Create a new UUID value.\n"), out
);
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 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
);
39 fputs(USAGE_SEPARATOR
, out
);
40 printf(USAGE_HELP_OPTIONS(18));
41 printf(USAGE_MAN_TAIL("uuidgen(1)"));
45 static char *unhex(const char *value
, size_t *valuelen
)
50 if (*valuelen
% 2 != 0) {
52 fprintf(stderr
, "%s: not a valid hex string\n", program_invocation_short_name
);
53 errtryhelp(EXIT_FAILURE
);
56 value2
= malloc(*valuelen
/ 2 + 1);
58 for (x
= n
= 0; n
< *valuelen
; n
++) {
60 if ('0' <= c
&& c
<= '9')
62 else if (('a' <= c
&& c
<= 'f') || ('A' <= c
&& c
<= 'F'))
63 x
+= (c
- 'A' + 10) & 0xf;
82 main (int argc
, char *argv
[])
85 int do_type
= 0, is_hex
= 0;
86 char str
[UUID_STR_LEN
];
87 char *namespace = NULL
, *name
= NULL
;
91 static const struct option longopts
[] = {
92 {"random", no_argument
, NULL
, 'r'},
93 {"time", no_argument
, NULL
, 't'},
94 {"version", no_argument
, NULL
, 'V'},
95 {"help", no_argument
, NULL
, 'h'},
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'},
104 setlocale(LC_ALL
, "");
105 bindtextdomain(PACKAGE
, LOCALEDIR
);
107 close_stdout_atexit();
109 while ((c
= getopt_long(argc
, argv
, "rtVhn:N:msx", longopts
, NULL
)) != -1)
112 do_type
= UUID_TYPE_DCE_TIME
;
115 do_type
= UUID_TYPE_DCE_RANDOM
;
124 do_type
= UUID_TYPE_DCE_MD5
;
127 do_type
= UUID_TYPE_DCE_SHA1
;
136 print_version(EXIT_SUCCESS
);
138 errtryhelp(EXIT_FAILURE
);
143 fprintf(stderr
, "%s: --namespace requires --name argument\n", program_invocation_short_name
);
144 errtryhelp(EXIT_FAILURE
);
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
);
152 fprintf(stderr
, "%s: --name requires --namespace argument\n", program_invocation_short_name
);
153 errtryhelp(EXIT_FAILURE
);
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
);
162 namelen
= strlen(name
);
164 name
= unhex(name
, &namelen
);
168 case UUID_TYPE_DCE_TIME
:
169 uuid_generate_time(uu
);
171 case UUID_TYPE_DCE_RANDOM
:
172 uuid_generate_random(uu
);
174 case UUID_TYPE_DCE_MD5
:
175 case UUID_TYPE_DCE_SHA1
:
176 if (namespace[0] == '@' && namespace[1] != '\0') {
177 const uuid_t
*uuidptr
;
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
);
184 memcpy(ns
, *uuidptr
, sizeof(ns
));
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
);
191 if (do_type
== UUID_TYPE_DCE_MD5
)
192 uuid_generate_md5(uu
, ns
, name
, namelen
);
194 uuid_generate_sha1(uu
, ns
, name
, namelen
);
201 uuid_unparse(uu
, str
);