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 printf(_(" available namespaces: %s\n"), "@dns @url @oid @x500");
36 fputs(_(" -N, --name name generate hash-based uuid from this name\n"), out
);
37 fputs(_(" -m, --md5 generate md5 hash\n"), out
);
38 fputs(_(" -s, --sha1 generate sha1 hash\n"), out
);
39 fputs(_(" -x, --hex interpret name as hex string\n"), out
);
40 fputs(USAGE_SEPARATOR
, out
);
41 printf(USAGE_HELP_OPTIONS(21));
42 printf(USAGE_MAN_TAIL("uuidgen(1)"));
46 static char *unhex(const char *value
, size_t *valuelen
)
51 if (*valuelen
% 2 != 0) {
53 warnx(_("not a valid hex string"));
54 errtryhelp(EXIT_FAILURE
);
57 value2
= malloc(*valuelen
/ 2 + 1);
59 for (x
= n
= 0; n
< *valuelen
; n
++) {
61 if ('0' <= c
&& c
<= '9')
63 else if (('a' <= c
&& c
<= 'f') || ('A' <= c
&& c
<= 'F'))
64 x
+= (c
- 'A' + 10) & 0xf;
83 main (int argc
, char *argv
[])
86 int do_type
= 0, is_hex
= 0;
87 char str
[UUID_STR_LEN
];
88 char *namespace = NULL
, *name
= NULL
;
92 static const struct option longopts
[] = {
93 {"random", no_argument
, NULL
, 'r'},
94 {"time", no_argument
, NULL
, 't'},
95 {"version", no_argument
, NULL
, 'V'},
96 {"help", no_argument
, NULL
, 'h'},
97 {"namespace", required_argument
, NULL
, 'n'},
98 {"name", required_argument
, NULL
, 'N'},
99 {"md5", no_argument
, NULL
, 'm'},
100 {"sha1", no_argument
, NULL
, 's'},
101 {"hex", no_argument
, NULL
, 'x'},
105 setlocale(LC_ALL
, "");
106 bindtextdomain(PACKAGE
, LOCALEDIR
);
108 close_stdout_atexit();
110 while ((c
= getopt_long(argc
, argv
, "rtVhn:N:msx", longopts
, NULL
)) != -1)
113 do_type
= UUID_TYPE_DCE_TIME
;
116 do_type
= UUID_TYPE_DCE_RANDOM
;
125 do_type
= UUID_TYPE_DCE_MD5
;
128 do_type
= UUID_TYPE_DCE_SHA1
;
137 print_version(EXIT_SUCCESS
);
139 errtryhelp(EXIT_FAILURE
);
144 warnx(_("--namespace requires --name argument"));
145 errtryhelp(EXIT_FAILURE
);
147 if (do_type
!= UUID_TYPE_DCE_MD5
&& do_type
!= UUID_TYPE_DCE_SHA1
) {
148 warnx(_("--namespace requires --md5 or --sha1"));
149 errtryhelp(EXIT_FAILURE
);
153 warnx(_("--name requires --namespace argument"));
154 errtryhelp(EXIT_FAILURE
);
156 if (do_type
== UUID_TYPE_DCE_MD5
|| do_type
== UUID_TYPE_DCE_SHA1
) {
157 warnx(_("--md5 or --sha1 requires --namespace argument"));
158 errtryhelp(EXIT_FAILURE
);
163 namelen
= strlen(name
);
165 name
= unhex(name
, &namelen
);
169 case UUID_TYPE_DCE_TIME
:
170 uuid_generate_time(uu
);
172 case UUID_TYPE_DCE_RANDOM
:
173 uuid_generate_random(uu
);
175 case UUID_TYPE_DCE_MD5
:
176 case UUID_TYPE_DCE_SHA1
:
177 if (namespace[0] == '@' && namespace[1] != '\0') {
178 const uuid_t
*uuidptr
;
180 uuidptr
= uuid_get_template(&namespace[1]);
181 if (uuidptr
== NULL
) {
182 warnx(_("unknown namespace alias: '%s'"), namespace);
183 errtryhelp(EXIT_FAILURE
);
185 memcpy(ns
, *uuidptr
, sizeof(ns
));
187 if (uuid_parse(namespace, ns
) != 0) {
188 warnx(_("invalid uuid for namespace: '%s'"), namespace);
189 errtryhelp(EXIT_FAILURE
);
192 if (do_type
== UUID_TYPE_DCE_MD5
)
193 uuid_generate_md5(uu
, ns
, name
, namelen
);
195 uuid_generate_sha1(uu
, ns
, name
, namelen
);
202 uuid_unparse(uu
, str
);