umka/tools/gensamehash.c

126 lines
3.0 KiB
C

/*
SPDX-License-Identifier: GPL-2.0-or-later
UMKa - User-Mode KolibriOS developer tools
gensamehash - make directories with same names inside: dirname/dirname,
useful for search testing
Copyright (C) 2022 Ivan Baravy <dunkaist@gmail.com>
*/
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <signal.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#define NUM_LEN 10
#define rol32(x,y) (((x) << (y)) | ((x) >> (32 - (y))))
// the hash function has been taken from XFS docs with minor edits
uint32_t xfs_da_hashname(const char *name, int namelen) {
uint32_t hash;
/*
* Do four characters at a time as long as we can.
*/
for (hash = 0; namelen >= 4; namelen -= 4, name += 4) {
hash = (name[0] << 21) ^ (name[1] << 14) ^ (name[2] << 7) ^
(name[3] << 0) ^ rol32(hash, 7 * 4);
}
/*
* Now do the rest of the characters.
*/
switch (namelen) {
case 3:
return (name[0] << 14) ^ (name[1] << 7) ^ (name[2] << 0) ^
rol32(hash, 7 * 3);
case 2:
return (name[0] << 7) ^ (name[1] << 0) ^ rol32(hash, 7 * 2);
case 1:
return (name[0] << 0) ^ rol32(hash, 7 * 1);
default: /* case 0: */
return hash;
}
}
char name[256];
char hash_filename[256];
void increment(char *num) {
for (char *d = num + NUM_LEN - 1; d >= num; d--) {
switch (d[0]) {
case '9':
d[0] = 'A';
return;
case 'Z':
d[0] = 'a';
return;
case 'z':
d[0] = '0';
break;
default:
d[0]++;
return;
}
}
}
void int_handler(int signo, siginfo_t *info, void *context) {
(void)signo;
(void)info;
(void)context;
fprintf(stderr, "# cur name is %s\n", name);
}
int main(int argc, char *argv[])
{
uint32_t hash;
int hash_cnt = 0;
uint64_t start_num;
if (argc != 4) {
fprintf(stderr, "gensamehash <hash> <hash_cnt> <start_num>\n");
exit(1);
}
hash = strtoul(argv[1], NULL, 16);
sscanf(argv[2], "%i", &hash_cnt);
sscanf(argv[3], "%" SCNu64, &start_num);
fprintf(stderr, "pid: %u\n", getpid());
sprintf(hash_filename, "hash_0x%8.8" PRIx32 ".%u", hash, getpid());
sprintf(name, "%10.10" PRIu64, start_num);
struct sigaction sa;
sa.sa_sigaction = int_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_SIGINFO;
if (sigaction(SIGUSR1, &sa, NULL) == -1) {
fprintf(stderr, "Can't install SIGUSR1 handler!\n");
exit(1);
}
while (true) {
uint32_t h = xfs_da_hashname(name, NUM_LEN);
if (h == hash) {
FILE *f = fopen(hash_filename, "a+");
fprintf(f, "%7.7u %s\n", hash_cnt, name);
fclose(f);
hash_cnt++;
}
// fprintf(stderr, "# hash of %s is 0x%8.8x\n", name, h);
increment(name);
}
return 0;
}