MCPcopy Create free account
hub / github.com/eggert/tz / random_dirent

Function random_dirent

zic.c:1549–1595  ·  view source on GitHub ↗

Generate a randomish name in the same directory as *NAME. If *NAMEALLOC, put the name into *NAMEALLOC which is assumed to be that returned by a previous call and is thus already almost set up and equal to *NAME; otherwise, allocate a new name and put its address into both *NAMEALLOC and *NAME. */

Source from the content-addressed store, hash-verified

1547 that returned by a previous call and is thus already almost set up
1548 and equal to *NAME; otherwise, allocate a new name and put its
1549 address into both *NAMEALLOC and *NAME. */
1550static void
1551random_dirent(char const **name, char **namealloc)
1552{
1553 char const *src = *name;
1554 char *dst = *namealloc;
1555 static char const prefix[] = ".zic";
1556 static char const alphabet[] =
1557 "abcdefghijklmnopqrstuvwxyz"
1558 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1559 "0123456789";
1560 enum { prefixlen = sizeof prefix - 1, alphabetlen = sizeof alphabet - 1 };
1561 int suffixlen = 6;
1562 char const *lastslash = strrchr(src, '/');
1563 ptrdiff_t dirlen = lastslash ? lastslash + 1 - src : 0;
1564 int i;
1565 uint_fast64_t r;
1566 uint_fast64_t base = alphabetlen;
1567
1568 /* BASE**6 */
1569 uint_fast64_t base__6 = base * base * base * base * base * base;
1570
1571 /* The largest uintmax_t that is a multiple of BASE**6. Any random
1572 uintmax_t value that is this value or greater, yields a biased
1573 remainder when divided by BASE**6. UNFAIR_MIN equals the
1574 mathematical value of ((UINTMAX_MAX + 1) - (UINTMAX_MAX + 1) % BASE**6)
1575 computed without overflow. */
1576 uint_fast64_t unfair_min = - ((UINTMAX_MAX % base__6 + 1) % base__6);
1577
1578 if (!dst) {
1579 char *cp = dst = xmalloc(size_sum(dirlen, prefixlen + suffixlen + 1));
1580 cp = mempcpy(cp, src, dirlen);
1581 cp = mempcpy(cp, prefix, prefixlen);
1582 cp[suffixlen] = '\0';
1583 *name = *namealloc = dst;
1584 }
1585
1586 for (;; check_for_signal()) {
1587 r = get_rand_u64();
1588 if (r < unfair_min)
1589 break;
1590 }
1591
1592 for (i = 0; i < suffixlen; i++) {
1593 dst[dirlen + prefixlen + i] = alphabet[r % alphabetlen];
1594 r /= alphabetlen;
1595 }
1596}
1597
1598/* For diagnostics the directory, and file name relative to that

Callers 2

open_outfileFunction · 0.85
dolinkFunction · 0.85

Calls 5

size_sumFunction · 0.85
mempcpyFunction · 0.85
check_for_signalFunction · 0.85
get_rand_u64Function · 0.85
xmallocFunction · 0.70

Tested by

no test coverage detected