summaryrefslogtreecommitdiffstats
path: root/misc-utils/uuidgen.c
diff options
context:
space:
mode:
Diffstat (limited to 'misc-utils/uuidgen.c')
-rw-r--r--misc-utils/uuidgen.c209
1 files changed, 209 insertions, 0 deletions
diff --git a/misc-utils/uuidgen.c b/misc-utils/uuidgen.c
new file mode 100644
index 0000000..c197069
--- /dev/null
+++ b/misc-utils/uuidgen.c
@@ -0,0 +1,209 @@
+/*
+ * gen_uuid.c --- generate a DCE-compatible uuid
+ *
+ * Copyright (C) 1999, Andreas Dilger and Theodore Ts'o
+ *
+ * %Begin-Header%
+ * This file may be redistributed under the terms of the GNU Public
+ * License.
+ * %End-Header%
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+#include "uuid.h"
+#include "nls.h"
+#include "c.h"
+#include "closestream.h"
+
+static void __attribute__((__noreturn__)) usage(void)
+{
+ FILE *out = stdout;
+ fputs(USAGE_HEADER, out);
+ fprintf(out,
+ _(" %s [options]\n"), program_invocation_short_name);
+
+ fputs(USAGE_SEPARATOR, out);
+ fputs(_("Create a new UUID value.\n"), out);
+
+ fputs(USAGE_OPTIONS, out);
+ fputs(_(" -r, --random generate random-based uuid\n"), out);
+ fputs(_(" -t, --time generate time-based uuid\n"), out);
+ fputs(_(" -n, --namespace ns generate hash-based uuid in this namespace\n"), out);
+ fputs(_(" -N, --name name generate hash-based uuid from this name\n"), out);
+ fputs(_(" -m, --md5 generate md5 hash\n"), out);
+ fputs(_(" -s, --sha1 generate sha1 hash\n"), out);
+ fputs(_(" -x, --hex interpret name as hex string\n"), out);
+ fputs(USAGE_SEPARATOR, out);
+ printf(USAGE_HELP_OPTIONS(18));
+ printf(USAGE_MAN_TAIL("uuidgen(1)"));
+ exit(EXIT_SUCCESS);
+}
+
+static char *unhex(const char *value, size_t *valuelen)
+{
+ char c, *value2;
+ unsigned n, x;
+
+ if (*valuelen % 2 != 0) {
+badstring:
+ fprintf(stderr, "%s: not a valid hex string\n", program_invocation_short_name);
+ errtryhelp(EXIT_FAILURE);
+ }
+
+ value2 = malloc(*valuelen / 2 + 1);
+
+ for (x = n = 0; n < *valuelen; n++) {
+ c = value[n];
+ if ('0' <= c && c <= '9')
+ x += c - '0';
+ else if (('a' <= c && c <= 'f') || ('A' <= c && c <= 'F'))
+ x += (c - 'A' + 10) & 0xf;
+ else
+ goto badstring;
+
+ if (n % 2 == 0)
+ x *= 16;
+ else {
+ value2[n / 2] = x;
+ x = 0;
+ }
+ }
+ value2[n / 2] = '\0';
+
+ *valuelen = (n / 2);
+
+ return value2;
+}
+
+int
+main (int argc, char *argv[])
+{
+ int c;
+ int do_type = 0, is_hex = 0;
+ char str[UUID_STR_LEN];
+ char *namespace = NULL, *name = NULL;
+ size_t namelen = 0;
+ uuid_t ns, uu;
+
+ static const struct option longopts[] = {
+ {"random", no_argument, NULL, 'r'},
+ {"time", no_argument, NULL, 't'},
+ {"version", no_argument, NULL, 'V'},
+ {"help", no_argument, NULL, 'h'},
+ {"namespace", required_argument, NULL, 'n'},
+ {"name", required_argument, NULL, 'N'},
+ {"md5", no_argument, NULL, 'm'},
+ {"sha1", no_argument, NULL, 's'},
+ {"hex", no_argument, NULL, 'x'},
+ {NULL, 0, NULL, 0}
+ };
+
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+ atexit(close_stdout);
+
+ while ((c = getopt_long(argc, argv, "rtVhn:N:msx", longopts, NULL)) != -1)
+ switch (c) {
+ case 't':
+ do_type = UUID_TYPE_DCE_TIME;
+ break;
+ case 'r':
+ do_type = UUID_TYPE_DCE_RANDOM;
+ break;
+ case 'V':
+ printf(UTIL_LINUX_VERSION);
+ return EXIT_SUCCESS;
+ case 'n':
+ namespace = optarg;
+ break;
+ case 'N':
+ name = optarg;
+ break;
+ case 'm':
+ do_type = UUID_TYPE_DCE_MD5;
+ break;
+ case 's':
+ do_type = UUID_TYPE_DCE_SHA1;
+ break;
+ case 'x':
+ is_hex = 1;
+ break;
+ case 'h':
+ usage();
+ default:
+ errtryhelp(EXIT_FAILURE);
+ }
+
+ if (namespace) {
+ if (!name) {
+ fprintf(stderr, "%s: --namespace requires --name argument\n", program_invocation_short_name);
+ errtryhelp(EXIT_FAILURE);
+ }
+ if (do_type != UUID_TYPE_DCE_MD5 && do_type != UUID_TYPE_DCE_SHA1) {
+ fprintf(stderr, "%s: --namespace requires --md5 or --sha1\n", program_invocation_short_name);
+ errtryhelp(EXIT_FAILURE);
+ }
+ } else {
+ if (name) {
+ fprintf(stderr, "%s: --name requires --namespace argument\n", program_invocation_short_name);
+ errtryhelp(EXIT_FAILURE);
+ }
+ if (do_type == UUID_TYPE_DCE_MD5 || do_type == UUID_TYPE_DCE_SHA1) {
+ fprintf(stderr, "%s: --md5 or --sha1 require --namespace\n", program_invocation_short_name);
+ errtryhelp(EXIT_FAILURE);
+ }
+ }
+
+ if (name) {
+ namelen = strlen(name);
+ if (is_hex)
+ name = unhex(name, &namelen);
+ }
+
+ switch (do_type) {
+ case UUID_TYPE_DCE_TIME:
+ uuid_generate_time(uu);
+ break;
+ case UUID_TYPE_DCE_RANDOM:
+ uuid_generate_random(uu);
+ break;
+ case UUID_TYPE_DCE_MD5:
+ case UUID_TYPE_DCE_SHA1:
+ if (namespace[0] == '@' && namespace[1] != '\0') {
+ const uuid_t *uuidptr;
+
+ uuidptr = uuid_get_template(&namespace[1]);
+ if (uuidptr == NULL) {
+ fprintf(stderr, "%s: unknown namespace alias '%s'\n", program_invocation_short_name, namespace);
+ errtryhelp(EXIT_FAILURE);
+ }
+ memcpy(ns, *uuidptr, sizeof(ns));
+ } else {
+ if (uuid_parse(namespace, ns) != 0) {
+ fprintf(stderr, "%s: invalid uuid for namespace '%s'\n", program_invocation_short_name, namespace);
+ errtryhelp(EXIT_FAILURE);
+ }
+ }
+ if (do_type == UUID_TYPE_DCE_MD5)
+ uuid_generate_md5(uu, ns, name, namelen);
+ else
+ uuid_generate_sha1(uu, ns, name, namelen);
+ break;
+ default:
+ uuid_generate(uu);
+ break;
+ }
+
+ uuid_unparse(uu, str);
+
+ printf("%s\n", str);
+
+ if (is_hex)
+ free(name);
+
+ return EXIT_SUCCESS;
+}