diff options
Diffstat (limited to 'misc-utils/uuidgen.c')
-rw-r--r-- | misc-utils/uuidgen.c | 209 |
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; +} |