diff options
-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 |