1/* vi: set sw=4 ts=4: */ 2/* 3 * Utility routines. 4 * 5 * Copyright (C) many different people. 6 * If you wrote this, please acknowledge your work. 7 * 8 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 9 */ 10 11#include "libbb.h" 12 13typedef struct ino_dev_hash_bucket_struct { 14 ino_t ino; 15 dev_t dev; 16 /* 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 */ 26 char name[1]; 27} ino_dev_hashtable_bucket_t; 28 29#define HASH_SIZE 311u /* Should be prime */ 30#define hash_inode(i) ((unsigned)(i) % HASH_SIZE) 31 32/* array of [HASH_SIZE] elements */ 33static ino_dev_hashtable_bucket_t **ino_dev_hashtable; 34 35/* 36 * Return name if statbuf->st_ino && statbuf->st_dev are recorded in 37 * ino_dev_hashtable, else return NULL 38 */ 39char* FAST_FUNC is_in_ino_dev_hashtable(const struct stat *statbuf) 40{ 41 ino_dev_hashtable_bucket_t *bucket; 42 43 if (!ino_dev_hashtable) 44 return NULL; 45 46 bucket = ino_dev_hashtable[hash_inode(statbuf->st_ino)]; 47 while (bucket != NULL) { 48 if ((bucket->ino == statbuf->st_ino) 49 && (bucket->dev == statbuf->st_dev) 50 && (bucket->isdir == !!S_ISDIR(statbuf->st_mode)) 51 ) { 52 return bucket->name; 53 } 54 bucket = bucket->next; 55 } 56 return NULL; 57} 58 59/* Add statbuf to statbuf hash table */ 60void FAST_FUNC add_to_ino_dev_hashtable(const struct stat *statbuf, const char *name) 61{ 62 int i; 63 ino_dev_hashtable_bucket_t *bucket; 64 65 if (!name) 66 name = ""; 67 bucket = xmalloc(sizeof(ino_dev_hashtable_bucket_t) + strlen(name)); 68 bucket->ino = statbuf->st_ino; 69 bucket->dev = statbuf->st_dev; 70 bucket->isdir = !!S_ISDIR(statbuf->st_mode); 71 strcpy(bucket->name, name); 72 73 if (!ino_dev_hashtable) 74 ino_dev_hashtable = xzalloc(HASH_SIZE * sizeof(*ino_dev_hashtable)); 75 76 i = hash_inode(statbuf->st_ino); 77 bucket->next = ino_dev_hashtable[i]; 78 ino_dev_hashtable[i] = bucket; 79} 80 81#if ENABLE_DU || ENABLE_FEATURE_CLEAN_UP 82/* Clear statbuf hash table */ 83void FAST_FUNC reset_ino_dev_hashtable(void) 84{ 85 int i; 86 ino_dev_hashtable_bucket_t *bucket, *next; 87 88 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; 98 } 99 } 100 free(ino_dev_hashtable); 101 ino_dev_hashtable = NULL; 102} 103#endif 104