blob: 4142813e38c06cc9b108a64cbc218c3f13ddd686 [file] [log] [blame]
Eric Andersenaad1a882001-03-16 22:47:14 +00001/* vi: set sw=4 ts=4: */
2/*
3 * Utility routines.
4 *
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005 * Copyright (C) many different people.
Eric Andersencb81e642003-07-14 21:21:08 +00006 * If you wrote this, please acknowledge your work.
Eric Andersenaad1a882001-03-16 22:47:14 +00007 *
Denys Vlasenko0ef64bd2010-08-16 20:14:46 +02008 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
Eric Andersenaad1a882001-03-16 22:47:14 +00009 */
Eric Andersenaad1a882001-03-16 22:47:14 +000010#include "libbb.h"
11
Denis Vlasenko6ef06ee2007-03-14 22:06:01 +000012typedef struct ino_dev_hash_bucket_struct {
Denis Vlasenko6ef06ee2007-03-14 22:06:01 +000013 ino_t ino;
14 dev_t dev;
Denys Vlasenko83bc4332014-02-25 15:27:58 +010015 /*
16 * Above fields can be 64-bit, while pointer may be 32-bit.
17 * Putting "next" field here may reduce size of this struct:
18 */
19 struct ino_dev_hash_bucket_struct *next;
20 /*
21 * Reportedly, on cramfs a file and a dir can have same ino.
22 * Need to also remember "file/dir" bit:
23 */
24 char isdir; /* bool */
Denis Vlasenko6ef06ee2007-03-14 22:06:01 +000025 char name[1];
26} ino_dev_hashtable_bucket_t;
27
Denys Vlasenko83bc4332014-02-25 15:27:58 +010028#define HASH_SIZE 311u /* Should be prime */
29#define hash_inode(i) ((unsigned)(i) % HASH_SIZE)
Eric Andersenaad1a882001-03-16 22:47:14 +000030
Denis Vlasenko6ef06ee2007-03-14 22:06:01 +000031/* array of [HASH_SIZE] elements */
32static ino_dev_hashtable_bucket_t **ino_dev_hashtable;
Eric Andersenaad1a882001-03-16 22:47:14 +000033
34/*
Denis Vlasenko6ef06ee2007-03-14 22:06:01 +000035 * Return name if statbuf->st_ino && statbuf->st_dev are recorded in
36 * ino_dev_hashtable, else return NULL
Eric Andersenaad1a882001-03-16 22:47:14 +000037 */
Denis Vlasenkodefc1ea2008-06-27 02:52:20 +000038char* FAST_FUNC is_in_ino_dev_hashtable(const struct stat *statbuf)
Eric Andersenaad1a882001-03-16 22:47:14 +000039{
40 ino_dev_hashtable_bucket_t *bucket;
41
Denis Vlasenko6ef06ee2007-03-14 22:06:01 +000042 if (!ino_dev_hashtable)
43 return NULL;
44
Eric Andersenaad1a882001-03-16 22:47:14 +000045 bucket = ino_dev_hashtable[hash_inode(statbuf->st_ino)];
46 while (bucket != NULL) {
Denis Vlasenko6ef06ee2007-03-14 22:06:01 +000047 if ((bucket->ino == statbuf->st_ino)
48 && (bucket->dev == statbuf->st_dev)
Denys Vlasenko83bc4332014-02-25 15:27:58 +010049 && (bucket->isdir == !!S_ISDIR(statbuf->st_mode))
Denis Vlasenko6ef06ee2007-03-14 22:06:01 +000050 ) {
51 return bucket->name;
52 }
53 bucket = bucket->next;
Eric Andersenaad1a882001-03-16 22:47:14 +000054 }
Denis Vlasenko6ef06ee2007-03-14 22:06:01 +000055 return NULL;
Eric Andersenaad1a882001-03-16 22:47:14 +000056}
57
58/* Add statbuf to statbuf hash table */
Denis Vlasenkodefc1ea2008-06-27 02:52:20 +000059void FAST_FUNC add_to_ino_dev_hashtable(const struct stat *statbuf, const char *name)
Eric Andersenaad1a882001-03-16 22:47:14 +000060{
61 int i;
Eric Andersenaad1a882001-03-16 22:47:14 +000062 ino_dev_hashtable_bucket_t *bucket;
Eric Andersenc7bda1c2004-03-15 08:29:22 +000063
Denis Vlasenko6ef06ee2007-03-14 22:06:01 +000064 if (!name)
65 name = "";
66 bucket = xmalloc(sizeof(ino_dev_hashtable_bucket_t) + strlen(name));
Eric Andersenaad1a882001-03-16 22:47:14 +000067 bucket->ino = statbuf->st_ino;
68 bucket->dev = statbuf->st_dev;
Denys Vlasenko83bc4332014-02-25 15:27:58 +010069 bucket->isdir = !!S_ISDIR(statbuf->st_mode);
Denis Vlasenko6ef06ee2007-03-14 22:06:01 +000070 strcpy(bucket->name, name);
71
72 if (!ino_dev_hashtable)
73 ino_dev_hashtable = xzalloc(HASH_SIZE * sizeof(*ino_dev_hashtable));
74
Denys Vlasenko83bc4332014-02-25 15:27:58 +010075 i = hash_inode(statbuf->st_ino);
Eric Andersenaad1a882001-03-16 22:47:14 +000076 bucket->next = ino_dev_hashtable[i];
77 ino_dev_hashtable[i] = bucket;
78}
79
Denis Vlasenko618a3022008-11-11 21:15:56 +000080#if ENABLE_DU || ENABLE_FEATURE_CLEAN_UP
Eric Andersenaad1a882001-03-16 22:47:14 +000081/* Clear statbuf hash table */
Denis Vlasenkodefc1ea2008-06-27 02:52:20 +000082void FAST_FUNC reset_ino_dev_hashtable(void)
Eric Andersenaad1a882001-03-16 22:47:14 +000083{
84 int i;
Denys Vlasenko12916b92014-02-25 15:09:01 +010085 ino_dev_hashtable_bucket_t *bucket, *next;
Eric Andersenaad1a882001-03-16 22:47:14 +000086
Denys Vlasenko12916b92014-02-25 15:09:01 +010087 if (!ino_dev_hashtable)
88 return;
89
90 for (i = 0; i < HASH_SIZE; i++) {
91 bucket = ino_dev_hashtable[i];
92
93 while (bucket != NULL) {
94 next = bucket->next;
95 free(bucket);
96 bucket = next;
Eric Andersenaad1a882001-03-16 22:47:14 +000097 }
98 }
Denis Vlasenko6ef06ee2007-03-14 22:06:01 +000099 free(ino_dev_hashtable);
100 ino_dev_hashtable = NULL;
Eric Andersenaad1a882001-03-16 22:47:14 +0000101}
Eric Andersen8876fb22003-06-20 09:01:58 +0000102#endif