(root)/
util-linux-2.39/
misc-utils/
uuidgen.c
       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>
      13  #include <stdlib.h>
      14  #include <getopt.h>
      15  
      16  #include "uuid.h"
      17  #include "nls.h"
      18  #include "c.h"
      19  #include "closestream.h"
      20  
      21  static void __attribute__((__noreturn__)) usage(void)
      22  {
      23  	FILE *out = stdout;
      24  	fputs(USAGE_HEADER, out);
      25  	fprintf(out,
      26  	      _(" %s [options]\n"), program_invocation_short_name);
      27  
      28  	fputs(USAGE_SEPARATOR, out);
      29  	fputs(_("Create a new UUID value.\n"), out);
      30  
      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)"));
      43  	exit(EXIT_SUCCESS);
      44  }
      45  
      46  static char *unhex(const char *value, size_t *valuelen)
      47  {
      48  	char c, *value2;
      49  	unsigned n, x;
      50  
      51  	if (*valuelen % 2 != 0) {
      52  badstring:
      53  		warnx(_("not a valid hex string"));
      54  		errtryhelp(EXIT_FAILURE);
      55  	}
      56  
      57  	value2 = malloc(*valuelen / 2 + 1);
      58  
      59  	for (x = n = 0; n < *valuelen; n++) {
      60  		c = value[n];
      61  		if ('0' <= c && c <= '9')
      62  			x += c - '0';
      63  		else if (('a' <= c && c <= 'f') || ('A' <= c && c <= 'F'))
      64  			x += (c - 'A' + 10) & 0xf;
      65  		else
      66  			goto badstring;
      67  
      68  		if (n % 2 == 0)
      69  			x *= 16;
      70  		else {
      71  			value2[n / 2] = x;
      72  			x = 0;
      73  		}
      74  	}
      75  	value2[n / 2] = '\0';
      76  
      77  	*valuelen = (n / 2);
      78  
      79  	return value2;
      80  }
      81  
      82  int
      83  main (int argc, char *argv[])
      84  {
      85  	int    c;
      86  	int    do_type = 0, is_hex = 0;
      87  	char   str[UUID_STR_LEN];
      88  	char   *namespace = NULL, *name = NULL;
      89  	size_t namelen = 0;
      90  	uuid_t ns, uu;
      91  
      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'},
     102  		{NULL, 0, NULL, 0}
     103  	};
     104  
     105  	setlocale(LC_ALL, "");
     106  	bindtextdomain(PACKAGE, LOCALEDIR);
     107  	textdomain(PACKAGE);
     108  	close_stdout_atexit();
     109  
     110  	while ((c = getopt_long(argc, argv, "rtVhn:N:msx", longopts, NULL)) != -1)
     111  		switch (c) {
     112  		case 't':
     113  			do_type = UUID_TYPE_DCE_TIME;
     114  			break;
     115  		case 'r':
     116  			do_type = UUID_TYPE_DCE_RANDOM;
     117  			break;
     118  		case 'n':
     119  			namespace = optarg;
     120  			break;
     121  		case 'N':
     122  			name = optarg;
     123  			break;
     124  		case 'm':
     125  			do_type = UUID_TYPE_DCE_MD5;
     126  			break;
     127  		case 's':
     128  			do_type = UUID_TYPE_DCE_SHA1;
     129  			break;
     130  		case 'x':
     131  			is_hex = 1;
     132  			break;
     133  
     134  		case 'h':
     135  			usage();
     136  		case 'V':
     137  			print_version(EXIT_SUCCESS);
     138  		default:
     139  			errtryhelp(EXIT_FAILURE);
     140  		}
     141  
     142  	if (namespace) {
     143  		if (!name) {
     144  			warnx(_("--namespace requires --name argument"));
     145  			errtryhelp(EXIT_FAILURE);
     146  		}
     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);
     150  		}
     151  	} else {
     152  		if (name) {
     153  			warnx(_("--name requires --namespace argument"));
     154  			errtryhelp(EXIT_FAILURE);
     155  		}
     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);
     159  		}
     160  	}
     161  
     162  	if (name) {
     163  		namelen = strlen(name);
     164  		if (is_hex)
     165  			name = unhex(name, &namelen);
     166  	}
     167  
     168  	switch (do_type) {
     169  	case UUID_TYPE_DCE_TIME:
     170  		uuid_generate_time(uu);
     171  		break;
     172  	case UUID_TYPE_DCE_RANDOM:
     173  		uuid_generate_random(uu);
     174  		break;
     175  	case UUID_TYPE_DCE_MD5:
     176  	case UUID_TYPE_DCE_SHA1:
     177  		if (namespace[0] == '@' && namespace[1] != '\0') {
     178  			const uuid_t *uuidptr;
     179  
     180  			uuidptr = uuid_get_template(&namespace[1]);
     181  			if (uuidptr == NULL) {
     182  				warnx(_("unknown namespace alias: '%s'"), namespace);
     183  				errtryhelp(EXIT_FAILURE);
     184  			}
     185  			memcpy(ns, *uuidptr, sizeof(ns));
     186  		} else {
     187  			if (uuid_parse(namespace, ns) != 0) {
     188  				warnx(_("invalid uuid for namespace: '%s'"), namespace);
     189  				errtryhelp(EXIT_FAILURE);
     190  			}
     191  		}
     192  		if (do_type == UUID_TYPE_DCE_MD5)
     193  			uuid_generate_md5(uu, ns, name, namelen);
     194  		else
     195  			uuid_generate_sha1(uu, ns, name, namelen);
     196  		break;
     197  	default:
     198  		uuid_generate(uu);
     199  		break;
     200  	}
     201  
     202  	uuid_unparse(uu, str);
     203  
     204  	printf("%s\n", str);
     205  
     206  	if (is_hex)
     207  		free(name);
     208  
     209  	return EXIT_SUCCESS;
     210  }