inode_hash.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  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. #include "libbb.h"
  11. typedef struct ino_dev_hash_bucket_struct {
  12. ino_t ino;
  13. dev_t dev;
  14. /*
  15. * Above fields can be 64-bit, while pointer may be 32-bit.
  16. * Putting "next" field here may reduce size of this struct:
  17. */
  18. struct ino_dev_hash_bucket_struct *next;
  19. /*
  20. * Reportedly, on cramfs a file and a dir can have same ino.
  21. * Need to also remember "file/dir" bit:
  22. */
  23. char isdir; /* bool */
  24. char name[1];
  25. } ino_dev_hashtable_bucket_t;
  26. #define HASH_SIZE 311u /* Should be prime */
  27. #define hash_inode(i) ((unsigned)(i) % HASH_SIZE)
  28. /* array of [HASH_SIZE] elements */
  29. static ino_dev_hashtable_bucket_t **ino_dev_hashtable;
  30. /*
  31. * Return name if statbuf->st_ino && statbuf->st_dev are recorded in
  32. * ino_dev_hashtable, else return NULL
  33. */
  34. char* FAST_FUNC is_in_ino_dev_hashtable(const struct stat *statbuf)
  35. {
  36. ino_dev_hashtable_bucket_t *bucket;
  37. if (!ino_dev_hashtable)
  38. return NULL;
  39. bucket = ino_dev_hashtable[hash_inode(statbuf->st_ino)];
  40. while (bucket != NULL) {
  41. if ((bucket->ino == statbuf->st_ino)
  42. && (bucket->dev == statbuf->st_dev)
  43. && (bucket->isdir == !!S_ISDIR(statbuf->st_mode))
  44. ) {
  45. return bucket->name;
  46. }
  47. bucket = bucket->next;
  48. }
  49. return NULL;
  50. }
  51. /* Add statbuf to statbuf hash table */
  52. void FAST_FUNC add_to_ino_dev_hashtable(const struct stat *statbuf, const char *name)
  53. {
  54. int i;
  55. ino_dev_hashtable_bucket_t *bucket;
  56. if (!name)
  57. name = "";
  58. bucket = xmalloc(sizeof(ino_dev_hashtable_bucket_t) + strlen(name));
  59. bucket->ino = statbuf->st_ino;
  60. bucket->dev = statbuf->st_dev;
  61. bucket->isdir = !!S_ISDIR(statbuf->st_mode);
  62. strcpy(bucket->name, name);
  63. if (!ino_dev_hashtable)
  64. ino_dev_hashtable = xzalloc(HASH_SIZE * sizeof(*ino_dev_hashtable));
  65. i = hash_inode(statbuf->st_ino);
  66. bucket->next = ino_dev_hashtable[i];
  67. ino_dev_hashtable[i] = bucket;
  68. }
  69. #if ENABLE_FEATURE_CLEAN_UP
  70. /* Clear statbuf hash table */
  71. void FAST_FUNC reset_ino_dev_hashtable(void)
  72. {
  73. int i;
  74. ino_dev_hashtable_bucket_t *bucket, *next;
  75. if (!ino_dev_hashtable)
  76. return;
  77. for (i = 0; i < HASH_SIZE; i++) {
  78. bucket = ino_dev_hashtable[i];
  79. while (bucket != NULL) {
  80. next = bucket->next;
  81. free(bucket);
  82. bucket = next;
  83. }
  84. }
  85. free(ino_dev_hashtable);
  86. ino_dev_hashtable = NULL;
  87. }
  88. #endif