]> git.ipfire.org Git - thirdparty/util-linux.git/blame - misc-utils/uuidgen.c
Merge branch 'su_err_msg' of https://github.com/jhrozek/util-linux
[thirdparty/util-linux.git] / misc-utils / uuidgen.c
CommitLineData
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 21static 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
45static char *unhex(const char *value, size_t *valuelen)
46{
47 char c, *value2;
48 unsigned n, x;
49
50 if (*valuelen % 2 != 0) {
51badstring:
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
81int
82main (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);
2c308875 107 close_stdout_atexit();
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;
c6f1ec68
PP
117 case 'n':
118 namespace = optarg;
119 break;
120 case 'N':
121 name = optarg;
122 break;
123 case 'm':
124 do_type = UUID_TYPE_DCE_MD5;
125 break;
126 case 's':
127 do_type = UUID_TYPE_DCE_SHA1;
128 break;
129 case 'x':
130 is_hex = 1;
131 break;
2c308875 132
0379a55d 133 case 'h':
86be6a32 134 usage();
2c308875
KZ
135 case 'V':
136 print_version(EXIT_SUCCESS);
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}