diff options
| author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-03-14 22:06:01 +0000 |
|---|---|---|
| committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-03-14 22:06:01 +0000 |
| commit | 6ef06eeed435eee87a5b6141d1ad445174e8019b (patch) | |
| tree | 4e83de1e390e6b6e52befcbb4a9ab9cad553021f | |
| parent | 75ab6af71edb9e0e919a4e1e65bd7b45da93935b (diff) | |
| download | busybox-w32-6ef06eeed435eee87a5b6141d1ad445174e8019b.tar.gz busybox-w32-6ef06eeed435eee87a5b6141d1ad445174e8019b.tar.bz2 busybox-w32-6ef06eeed435eee87a5b6141d1ad445174e8019b.zip | |
stop using big static buffer for inode hash
| -rw-r--r-- | include/libbb.h | 5 | ||||
| -rw-r--r-- | libbb/copy_file.c | 23 | ||||
| -rw-r--r-- | libbb/inode_hash.c | 63 |
3 files changed, 48 insertions, 43 deletions
diff --git a/include/libbb.h b/include/libbb.h index 759eb8d15..632ed937d 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
| @@ -229,6 +229,7 @@ extern void trim(char *s); | |||
| 229 | extern char *skip_whitespace(const char *); | 229 | extern char *skip_whitespace(const char *); |
| 230 | extern char *skip_non_whitespace(const char *); | 230 | extern char *skip_non_whitespace(const char *); |
| 231 | 231 | ||
| 232 | //TODO: supply a pointer to char[11] buffer (avoid statics)? | ||
| 232 | extern const char *bb_mode_string(mode_t mode); | 233 | extern const char *bb_mode_string(mode_t mode); |
| 233 | extern int is_directory(const char *name, int followLinks, struct stat *statBuf); | 234 | extern int is_directory(const char *name, int followLinks, struct stat *statBuf); |
| 234 | extern int remove_file(const char *path, int flags); | 235 | extern int remove_file(const char *path, int flags); |
| @@ -556,9 +557,11 @@ extern int del_loop(const char *device); | |||
| 556 | extern int set_loop(char **device, const char *file, unsigned long long offset); | 557 | extern int set_loop(char **device, const char *file, unsigned long long offset); |
| 557 | 558 | ||
| 558 | 559 | ||
| 560 | //TODO: provide pointer to buf (avoid statics)? | ||
| 559 | const char *make_human_readable_str(unsigned long long size, | 561 | const char *make_human_readable_str(unsigned long long size, |
| 560 | unsigned long block_size, unsigned long display_unit); | 562 | unsigned long block_size, unsigned long display_unit); |
| 561 | 563 | ||
| 564 | //TODO: pass buf pointer or return allocated buf (avoid statics)? | ||
| 562 | char *bb_askpass(int timeout, const char * prompt); | 565 | char *bb_askpass(int timeout, const char * prompt); |
| 563 | int bb_ask_confirmation(void); | 566 | int bb_ask_confirmation(void); |
| 564 | int klogctl(int type, char * b, int len); | 567 | int klogctl(int type, char * b, int len); |
| @@ -624,7 +627,7 @@ extern void vfork_daemon_rexec(int nochdir, int noclose, | |||
| 624 | #endif | 627 | #endif |
| 625 | extern int get_terminal_width_height(const int fd, int *width, int *height); | 628 | extern int get_terminal_width_height(const int fd, int *width, int *height); |
| 626 | 629 | ||
| 627 | int is_in_ino_dev_hashtable(const struct stat *statbuf, char **name); | 630 | char *is_in_ino_dev_hashtable(const struct stat *statbuf); |
| 628 | void add_to_ino_dev_hashtable(const struct stat *statbuf, const char *name); | 631 | void add_to_ino_dev_hashtable(const struct stat *statbuf, const char *name); |
| 629 | void reset_ino_dev_hashtable(void); | 632 | void reset_ino_dev_hashtable(void); |
| 630 | #ifdef __GLIBC__ | 633 | #ifdef __GLIBC__ |
diff --git a/libbb/copy_file.c b/libbb/copy_file.c index 07564afd0..636fbdc1d 100644 --- a/libbb/copy_file.c +++ b/libbb/copy_file.c | |||
| @@ -172,22 +172,21 @@ int copy_file(const char *source, const char *dest, int flags) | |||
| 172 | if (ENABLE_FEATURE_PRESERVE_HARDLINKS) { | 172 | if (ENABLE_FEATURE_PRESERVE_HARDLINKS) { |
| 173 | char *link_name; | 173 | char *link_name; |
| 174 | 174 | ||
| 175 | if (!FLAGS_DEREF | 175 | if (!FLAGS_DEREF) { |
| 176 | && is_in_ino_dev_hashtable(&source_stat, &link_name) | 176 | link_name = is_in_ino_dev_hashtable(&source_stat); |
| 177 | ) { | 177 | if (link_name) { |
| 178 | if (link(link_name, dest) < 0) { | ||
| 179 | ovr = retry_overwrite(dest, flags); | ||
| 180 | if (ovr <= 0) | ||
| 181 | return ovr; | ||
| 182 | if (link(link_name, dest) < 0) { | 178 | if (link(link_name, dest) < 0) { |
| 183 | bb_perror_msg("cannot create link '%s'", dest); | 179 | ovr = retry_overwrite(dest, flags); |
| 184 | return -1; | 180 | if (ovr <= 0) |
| 181 | return ovr; | ||
| 182 | if (link(link_name, dest) < 0) { | ||
| 183 | bb_perror_msg("cannot create link '%s'", dest); | ||
| 184 | return -1; | ||
| 185 | } | ||
| 185 | } | 186 | } |
| 187 | return 0; | ||
| 186 | } | 188 | } |
| 187 | return 0; | ||
| 188 | } | 189 | } |
| 189 | // TODO: probably is_in_.. and add_to_... | ||
| 190 | // can be combined: find_or_add_... | ||
| 191 | add_to_ino_dev_hashtable(&source_stat, dest); | 190 | add_to_ino_dev_hashtable(&source_stat, dest); |
| 192 | } | 191 | } |
| 193 | 192 | ||
diff --git a/libbb/inode_hash.c b/libbb/inode_hash.c index 2ac1623f4..55a7564ce 100644 --- a/libbb/inode_hash.c +++ b/libbb/inode_hash.c | |||
| @@ -13,41 +13,40 @@ | |||
| 13 | #include <string.h> | 13 | #include <string.h> |
| 14 | #include "libbb.h" | 14 | #include "libbb.h" |
| 15 | 15 | ||
| 16 | #define HASH_SIZE 311 /* Should be prime */ | ||
| 17 | #define hash_inode(i) ((i) % HASH_SIZE) | ||
| 18 | |||
| 19 | typedef struct ino_dev_hash_bucket_struct { | 16 | typedef struct ino_dev_hash_bucket_struct { |
| 20 | struct ino_dev_hash_bucket_struct *next; | 17 | struct ino_dev_hash_bucket_struct *next; |
| 21 | ino_t ino; | 18 | ino_t ino; |
| 22 | dev_t dev; | 19 | dev_t dev; |
| 23 | char name[1]; | 20 | char name[1]; |
| 24 | } ino_dev_hashtable_bucket_t; | 21 | } ino_dev_hashtable_bucket_t; |
| 25 | 22 | ||
| 26 | static ino_dev_hashtable_bucket_t *ino_dev_hashtable[HASH_SIZE]; | 23 | #define HASH_SIZE 311 /* Should be prime */ |
| 24 | #define hash_inode(i) ((i) % HASH_SIZE) | ||
| 25 | |||
| 26 | /* array of [HASH_SIZE] elements */ | ||
| 27 | static ino_dev_hashtable_bucket_t **ino_dev_hashtable; | ||
| 27 | 28 | ||
| 28 | /* | 29 | /* |
| 29 | * Return 1 if statbuf->st_ino && statbuf->st_dev are recorded in | 30 | * Return name if statbuf->st_ino && statbuf->st_dev are recorded in |
| 30 | * `ino_dev_hashtable', else return 0 | 31 | * ino_dev_hashtable, else return NULL |
| 31 | * | ||
| 32 | * If NAME is a non-NULL pointer to a character pointer, and there is | ||
| 33 | * a match, then set *NAME to the value of the name slot in that | ||
| 34 | * bucket. | ||
| 35 | */ | 32 | */ |
| 36 | int is_in_ino_dev_hashtable(const struct stat *statbuf, char **name) | 33 | char *is_in_ino_dev_hashtable(const struct stat *statbuf) |
| 37 | { | 34 | { |
| 38 | ino_dev_hashtable_bucket_t *bucket; | 35 | ino_dev_hashtable_bucket_t *bucket; |
| 39 | 36 | ||
| 37 | if (!ino_dev_hashtable) | ||
| 38 | return NULL; | ||
| 39 | |||
| 40 | bucket = ino_dev_hashtable[hash_inode(statbuf->st_ino)]; | 40 | bucket = ino_dev_hashtable[hash_inode(statbuf->st_ino)]; |
| 41 | while (bucket != NULL) { | 41 | while (bucket != NULL) { |
| 42 | if ((bucket->ino == statbuf->st_ino) && | 42 | if ((bucket->ino == statbuf->st_ino) |
| 43 | (bucket->dev == statbuf->st_dev)) | 43 | && (bucket->dev == statbuf->st_dev) |
| 44 | { | 44 | ) { |
| 45 | if (name) *name = bucket->name; | 45 | return bucket->name; |
| 46 | return 1; | 46 | } |
| 47 | } | 47 | bucket = bucket->next; |
| 48 | bucket = bucket->next; | ||
| 49 | } | 48 | } |
| 50 | return 0; | 49 | return NULL; |
| 51 | } | 50 | } |
| 52 | 51 | ||
| 53 | /* Add statbuf to statbuf hash table */ | 52 | /* Add statbuf to statbuf hash table */ |
| @@ -58,19 +57,21 @@ void add_to_ino_dev_hashtable(const struct stat *statbuf, const char *name) | |||
| 58 | ino_dev_hashtable_bucket_t *bucket; | 57 | ino_dev_hashtable_bucket_t *bucket; |
| 59 | 58 | ||
| 60 | i = hash_inode(statbuf->st_ino); | 59 | i = hash_inode(statbuf->st_ino); |
| 61 | s = name ? strlen(name) : 0; | 60 | if (!name) |
| 62 | bucket = xmalloc(sizeof(ino_dev_hashtable_bucket_t) + s); | 61 | name = ""; |
| 62 | bucket = xmalloc(sizeof(ino_dev_hashtable_bucket_t) + strlen(name)); | ||
| 63 | bucket->ino = statbuf->st_ino; | 63 | bucket->ino = statbuf->st_ino; |
| 64 | bucket->dev = statbuf->st_dev; | 64 | bucket->dev = statbuf->st_dev; |
| 65 | if (name) | 65 | strcpy(bucket->name, name); |
| 66 | strcpy(bucket->name, name); | 66 | |
| 67 | else | 67 | if (!ino_dev_hashtable) |
| 68 | bucket->name[0] = '\0'; | 68 | ino_dev_hashtable = xzalloc(HASH_SIZE * sizeof(*ino_dev_hashtable)); |
| 69 | |||
| 69 | bucket->next = ino_dev_hashtable[i]; | 70 | bucket->next = ino_dev_hashtable[i]; |
| 70 | ino_dev_hashtable[i] = bucket; | 71 | ino_dev_hashtable[i] = bucket; |
| 71 | } | 72 | } |
| 72 | 73 | ||
| 73 | #ifdef CONFIG_FEATURE_CLEAN_UP | 74 | #if ENABLE_FEATURE_CLEAN_UP |
| 74 | /* Clear statbuf hash table */ | 75 | /* Clear statbuf hash table */ |
| 75 | void reset_ino_dev_hashtable(void) | 76 | void reset_ino_dev_hashtable(void) |
| 76 | { | 77 | { |
| @@ -84,5 +85,7 @@ void reset_ino_dev_hashtable(void) | |||
| 84 | ino_dev_hashtable[i] = bucket; | 85 | ino_dev_hashtable[i] = bucket; |
| 85 | } | 86 | } |
| 86 | } | 87 | } |
| 88 | free(ino_dev_hashtable); | ||
| 89 | ino_dev_hashtable = NULL; | ||
| 87 | } | 90 | } |
| 88 | #endif | 91 | #endif |
