2 * Creates a bunch of files in the specified directory with the same
13 #include <sys/types.h>
16 #define rol32(x,y) (((x) << (y)) | ((x) >> (32 - (y))))
19 * Implement a simple hash on a character string.
20 * Rotate the hash value by 7 bits, then XOR each character in.
21 * This is implemented with some source-level loop unrolling.
23 static uint32_t xfs_da_hashname(const char *name, int namelen)
28 * Do four characters at a time as long as we can.
30 for (hash = 0; namelen >= 4; namelen -= 4, name += 4)
31 hash = (name[0] << 21) ^ (name[1] << 14) ^ (name[2] << 7) ^
32 (name[3] << 0) ^ rol32(hash, 7 * 4);
35 * Now do the rest of the characters.
39 return (name[0] << 14) ^ (name[1] << 7) ^ (name[2] << 0) ^
42 return (name[0] << 7) ^ (name[1] << 0) ^ rol32(hash, 7 * 2);
44 return (name[0] << 0) ^ rol32(hash, 7 * 1);
45 default: /* case 0: */
50 static int is_invalid_char(char c)
52 return (c <= ' ' || c > '~' || c == '/' || (c >= 'A' && c <= 'Z'));
55 static char random_char(void)
59 /* get a character of "0"-"9" or "a"-"z" */
63 return (c >= 10) ? c + 87 : c + 48;
66 static int generate_names(const char *path, long amount, uint32_t desired_hash)
69 char fullpath[PATH_MAX];
76 names = malloc(amount * sizeof(char *));
78 fprintf(stderr, "genhashnames: malloc(%lu) failed!\n",
79 amount * sizeof(char *));
83 strcpy(fullpath, path);
84 filename = fullpath + strlen(fullpath);
85 if (filename[-1] != '/')
88 for (count = 0; count < amount; count++) {
91 for (i = 0; i < 6; i++) {
92 filename[i] = random_char();
93 base_hash = filename[i] ^ rol32(base_hash, 7);
96 filename[i] = random_char();
97 base_hash = filename[i] ^ rol32(base_hash, 7);
99 hash = rol32(base_hash, 3) ^ desired_hash;
101 filename[i] = (hash >> 28) |
102 (random_char() & 0xf0);
103 if (is_invalid_char(filename[i]))
106 filename[i + 1] = (hash >> 21) & 0x7f;
107 if (is_invalid_char(filename[i + 1]))
109 filename[i + 2] = (hash >> 14) & 0x7f;
110 if (is_invalid_char(filename[i + 2]))
112 filename[i + 3] = (hash >> 7) & 0x7f;
113 if (is_invalid_char(filename[i + 3]))
115 filename[i + 4] = (hash ^ (filename[i] >> 4))
117 if (is_invalid_char(filename[i + 4]))
124 filename[i + 5] = '\0';
125 if (xfs_da_hashname(filename, i + 5) != desired_hash) {
126 fprintf(stderr, "genhashnames: Hash mismatch!\n");
130 for (i = 0; i < count; i++) {
131 if (strcmp(fullpath, names[i]) == 0)
135 names[count] = strdup(fullpath);
143 static void usage(void)
145 fprintf(stderr, "Usage: genhashnames <directory> <amount> "
146 "[seed] [hashvalue]\n");
150 int main(int argc, char **argv)
153 uint32_t desired_hash;
155 if (argc < 3 || argc > 5)
159 seed = strtol(argv[3], NULL, 0);
162 gettimeofday(&tv, NULL);
163 seed = tv.tv_usec / 1000 + (tv.tv_sec % 1000) * 1000;
168 * always generate hash from random so if hash is specified, random
169 * sequence is the same as a randomly generated hash of the same value.
171 desired_hash = (uint32_t)mrand48();
173 desired_hash = (uint32_t)strtoul(argv[4], NULL, 0);
175 fprintf(stderr, "seed = %ld, hash = 0x%08x\n", seed, desired_hash);
177 return generate_names(argv[1], strtol(argv[2], NULL, 0), desired_hash);