blob: f11c2afb2e786dff6d926e54d55583c3756307c3 [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 */
10
Eric Andersenaad1a882001-03-16 22:47:14 +000011#include "libbb.h"
12
Denis Vlasenko6ef06ee2007-03-14 22:06:01 +000013typedef struct ino_dev_hash_bucket_struct {
Denis Vlasenko6ef06ee2007-03-14 22:06:01 +000014 ino_t ino;
15 dev_t dev;
Denys Vlasenko83bc4332014-02-25 15:27:58 +010016 /*
17 * Above fields can be 64-bit, while pointer may be 32-bit.
18 * Putting "next" field here may reduce size of this struct:
19 */
20 struct ino_dev_hash_bucket_struct *next;
21 /*
22 * Reportedly, on cramfs a file and a dir can have same ino.
23 * Need to also remember "file/dir" bit:
24 */
25 char isdir; /* bool */
Denis Vlasenko6ef06ee2007-03-14 22:06:01 +000026 char name[1];
27} ino_dev_hashtable_bucket_t;
28
Denys Vlasenko83bc4332014-02-25 15:27:58 +010029#define HASH_SIZE 311u /* Should be prime */
30#define hash_inode(i) ((unsigned)(i) % HASH_SIZE)
Eric Andersenaad1a882001-03-16 22:47:14 +000031
Denis Vlasenko6ef06ee2007-03-14 22:06:01 +000032/* array of [HASH_SIZE] elements */
33static ino_dev_hashtable_bucket_t **ino_dev_hashtable;
Eric Andersenaad1a882001-03-16 22:47:14 +000034
35/*
Denis Vlasenko6ef06ee2007-03-14 22:06:01 +000036 * Return name if statbuf->st_ino && statbuf->st_dev are recorded in
37 * ino_dev_hashtable, else return NULL
Eric Andersenaad1a882001-03-16 22:47:14 +000038 */
Denis Vlasenkodefc1ea2008-06-27 02:52:20 +000039char* FAST_FUNC is_in_ino_dev_hashtable(const struct stat *statbuf)
Eric Andersenaad1a882001-03-16 22:47:14 +000040{
41 ino_dev_hashtable_bucket_t *bucket;
42
Denis Vlasenko6ef06ee2007-03-14 22:06:01 +000043 if (!ino_dev_hashtable)
44 return NULL;
45
Eric Andersenaad1a882001-03-16 22:47:14 +000046 bucket = ino_dev_hashtable[hash_inode(statbuf->st_ino)];
47 while (bucket != NULL) {
Denis Vlasenko6ef06ee2007-03-14 22:06:01 +000048 if ((bucket->ino == statbuf->st_ino)
49 && (bucket->dev == statbuf->st_dev)
Denys Vlasenko83bc4332014-02-25 15:27:58 +010050 && (bucket->isdir == !!S_ISDIR(statbuf->st_mode))
Denis Vlasenko6ef06ee2007-03-14 22:06:01 +000051 ) {
52 return bucket->name;
53 }
54 bucket = bucket->next;
Eric Andersenaad1a882001-03-16 22:47:14 +000055 }
Denis Vlasenko6ef06ee2007-03-14 22:06:01 +000056 return NULL;
Eric Andersenaad1a882001-03-16 22:47:14 +000057}
58
59/* Add statbuf to statbuf hash table */
Denis Vlasenkodefc1ea2008-06-27 02:52:20 +000060void FAST_FUNC add_to_ino_dev_hashtable(const struct stat *statbuf, const char *name)
Eric Andersenaad1a882001-03-16 22:47:14 +000061{
62 int i;
Eric Andersenaad1a882001-03-16 22:47:14 +000063 ino_dev_hashtable_bucket_t *bucket;
Eric Andersenc7bda1c2004-03-15 08:29:22 +000064
Denis Vlasenko6ef06ee2007-03-14 22:06:01 +000065 if (!name)
66 name = "";
67 bucket = xmalloc(sizeof(ino_dev_hashtable_bucket_t) + strlen(name));
Eric Andersenaad1a882001-03-16 22:47:14 +000068 bucket->ino = statbuf->st_ino;
69 bucket->dev = statbuf->st_dev;
Denys Vlasenko83bc4332014-02-25 15:27:58 +010070 bucket->isdir = !!S_ISDIR(statbuf->st_mode);
Denis Vlasenko6ef06ee2007-03-14 22:06:01 +000071 strcpy(bucket->name, name);
72
73 if (!ino_dev_hashtable)
74 ino_dev_hashtable = xzalloc(HASH_SIZE * sizeof(*ino_dev_hashtable));
75
Denys Vlasenko83bc4332014-02-25 15:27:58 +010076 i = hash_inode(statbuf->st_ino);
Eric Andersenaad1a882001-03-16 22:47:14 +000077 bucket->next = ino_dev_hashtable[i];
78 ino_dev_hashtable[i] = bucket;
79}
80
Denis Vlasenko618a3022008-11-11 21:15:56 +000081#if ENABLE_DU || ENABLE_FEATURE_CLEAN_UP
Eric Andersenaad1a882001-03-16 22:47:14 +000082/* Clear statbuf hash table */
Denis Vlasenkodefc1ea2008-06-27 02:52:20 +000083void FAST_FUNC reset_ino_dev_hashtable(void)
Eric Andersenaad1a882001-03-16 22:47:14 +000084{
85 int i;
Denys Vlasenko12916b92014-02-25 15:09:01 +010086 ino_dev_hashtable_bucket_t *bucket, *next;
Eric Andersenaad1a882001-03-16 22:47:14 +000087
Denys Vlasenko12916b92014-02-25 15:09:01 +010088 if (!ino_dev_hashtable)
89 return;
90
91 for (i = 0; i < HASH_SIZE; i++) {
92 bucket = ino_dev_hashtable[i];
93
94 while (bucket != NULL) {
95 next = bucket->next;
96 free(bucket);
97 bucket = next;
Eric Andersenaad1a882001-03-16 22:47:14 +000098 }
99 }
Denis Vlasenko6ef06ee2007-03-14 22:06:01 +0000100 free(ino_dev_hashtable);
101 ino_dev_hashtable = NULL;
Eric Andersenaad1a882001-03-16 22:47:14 +0000102}
Eric Andersen8876fb22003-06-20 09:01:58 +0000103#endif