diff options
Diffstat (limited to 'apps')
-rw-r--r-- | apps/tagcache.c | 130 |
1 files changed, 114 insertions, 16 deletions
diff --git a/apps/tagcache.c b/apps/tagcache.c index 3565d8e5d4..0831bab32d 100644 --- a/apps/tagcache.c +++ b/apps/tagcache.c | |||
@@ -60,6 +60,9 @@ | |||
60 | #include <stdio.h> | 60 | #include <stdio.h> |
61 | #include <stdlib.h> | 61 | #include <stdlib.h> |
62 | #include <ctype.h> | 62 | #include <ctype.h> |
63 | #ifdef APPLICATION | ||
64 | #include <unistd.h> /* readlink() */ | ||
65 | #endif | ||
63 | #include "config.h" | 66 | #include "config.h" |
64 | #include "ata_idle_notify.h" | 67 | #include "ata_idle_notify.h" |
65 | #include "thread.h" | 68 | #include "thread.h" |
@@ -77,6 +80,7 @@ | |||
77 | #include "dir.h" | 80 | #include "dir.h" |
78 | #include "filefuncs.h" | 81 | #include "filefuncs.h" |
79 | #include "structec.h" | 82 | #include "structec.h" |
83 | #include "debug.h" | ||
80 | 84 | ||
81 | #ifndef __PCTOOL__ | 85 | #ifndef __PCTOOL__ |
82 | #include "lang.h" | 86 | #include "lang.h" |
@@ -4189,6 +4193,88 @@ static void __attribute__ ((noinline)) check_ignore(const char *dirname, | |||
4189 | *unignore = file_exists(newpath); | 4193 | *unignore = file_exists(newpath); |
4190 | } | 4194 | } |
4191 | 4195 | ||
4196 | static struct search_roots_ll { | ||
4197 | const char *path; | ||
4198 | struct search_roots_ll * next; | ||
4199 | } roots_ll; | ||
4200 | |||
4201 | #ifdef APPLICATION | ||
4202 | /* | ||
4203 | * This adds a path to the search roots, possibly during traveling through | ||
4204 | * the filesystem. It only adds if the path is not inside an already existing | ||
4205 | * search root. | ||
4206 | * | ||
4207 | * Returns true if it added the path to the search roots | ||
4208 | * | ||
4209 | * Windows 2000 and greater supports symlinks, but they don't provide | ||
4210 | * realpath() or readlink(), and symlinks are rarely used on them so | ||
4211 | * ignore this for windows for now | ||
4212 | **/ | ||
4213 | static bool add_search_root(const char *name) | ||
4214 | { | ||
4215 | (void)name; | ||
4216 | #ifndef WIN32 | ||
4217 | struct search_roots_ll *this, *prev = NULL; | ||
4218 | char target[MAX_PATH]; | ||
4219 | char _abs_target[MAX_PATH]; | ||
4220 | char * abs_target; | ||
4221 | ssize_t len; | ||
4222 | |||
4223 | len = readlink(name, target, sizeof(target)); | ||
4224 | if (len < 0) | ||
4225 | return false; | ||
4226 | |||
4227 | target[len] = '\0'; | ||
4228 | /* realpath(target, NULL) doesn't work on android ... */ | ||
4229 | abs_target = realpath(target, _abs_target); | ||
4230 | if (abs_target == NULL) | ||
4231 | return false; | ||
4232 | |||
4233 | for(this = &roots_ll; this; prev = this, this = this->next) | ||
4234 | { | ||
4235 | size_t root_len = strlen(this->path); | ||
4236 | /* check if the link target is inside of an existing search root | ||
4237 | * don't add if target is inside, we'll scan it later */ | ||
4238 | if (!strncmp(this->path, abs_target, root_len)) | ||
4239 | return false; | ||
4240 | } | ||
4241 | |||
4242 | if (prev) | ||
4243 | { | ||
4244 | size_t len = strlen(abs_target) + 1; /* count \0 */ | ||
4245 | this = malloc(sizeof(struct search_roots_ll) + len ); | ||
4246 | if (!this || len > MAX_PATH) | ||
4247 | { | ||
4248 | logf("Error at adding a search root: %s", this ? "path too long":"OOM"); | ||
4249 | free(this); | ||
4250 | prev->next = NULL; | ||
4251 | } | ||
4252 | this->path = ((char*)this) + sizeof(struct search_roots_ll); | ||
4253 | strcpy((char*)this->path, abs_target); /* ok to cast const away here */ | ||
4254 | this->next = NULL; | ||
4255 | prev->next = this; | ||
4256 | logf("Added %s to the search roots\n", abs_target); | ||
4257 | return true; | ||
4258 | } | ||
4259 | #endif | ||
4260 | return false; | ||
4261 | } | ||
4262 | |||
4263 | static int free_search_roots(struct search_roots_ll * start) | ||
4264 | { | ||
4265 | int ret = 0; | ||
4266 | if (start->next) | ||
4267 | { | ||
4268 | ret += free_search_roots(start->next); | ||
4269 | ret += sizeof(struct search_roots_ll); | ||
4270 | free(start->next); | ||
4271 | } | ||
4272 | return ret; | ||
4273 | } | ||
4274 | #else /* native, simulator */ | ||
4275 | #define add_search_root(a) do {} while(0) | ||
4276 | #define free_search_roots(a) do {} while(0) | ||
4277 | #endif | ||
4192 | 4278 | ||
4193 | static bool check_dir(const char *dirname, int add_files) | 4279 | static bool check_dir(const char *dirname, int add_files) |
4194 | { | 4280 | { |
@@ -4203,7 +4289,6 @@ static bool check_dir(const char *dirname, int add_files) | |||
4203 | logf("tagcache: opendir(%s) failed", dirname); | 4289 | logf("tagcache: opendir(%s) failed", dirname); |
4204 | return false; | 4290 | return false; |
4205 | } | 4291 | } |
4206 | |||
4207 | /* check for a database.ignore and database.unignore */ | 4292 | /* check for a database.ignore and database.unignore */ |
4208 | check_ignore(dirname, &ignore, &unignore); | 4293 | check_ignore(dirname, &ignore, &unignore); |
4209 | 4294 | ||
@@ -4218,31 +4303,35 @@ static bool check_dir(const char *dirname, int add_files) | |||
4218 | while (!check_event_queue()) | 4303 | while (!check_event_queue()) |
4219 | #endif | 4304 | #endif |
4220 | { | 4305 | { |
4221 | struct dirent *entry; | 4306 | struct dirent *entry = readdir(dir); |
4222 | |||
4223 | entry = readdir(dir); | ||
4224 | |||
4225 | if (entry == NULL) | 4307 | if (entry == NULL) |
4226 | { | 4308 | { |
4227 | success = true; | 4309 | success = true; |
4228 | break ; | 4310 | break; |
4229 | } | 4311 | } |
4230 | 4312 | ||
4231 | struct dirinfo info = dir_get_info(dir, entry); | ||
4232 | |||
4233 | if (!strcmp((char *)entry->d_name, ".") || | 4313 | if (!strcmp((char *)entry->d_name, ".") || |
4234 | !strcmp((char *)entry->d_name, "..")) | 4314 | !strcmp((char *)entry->d_name, "..")) |
4235 | continue; | 4315 | continue; |
4236 | 4316 | ||
4317 | struct dirinfo info = dir_get_info(dir, entry); | ||
4318 | |||
4237 | yield(); | 4319 | yield(); |
4238 | 4320 | ||
4239 | len = strlen(curpath); | 4321 | len = strlen(curpath); |
4240 | snprintf(&curpath[len], sizeof(curpath) - len, "/%s", | 4322 | /* don't add an extra / for curpath == / */ |
4241 | entry->d_name); | 4323 | if (len <= 1) len = 0; |
4242 | 4324 | snprintf(&curpath[len], sizeof(curpath) - len, "/%s", entry->d_name); | |
4325 | |||
4243 | processed_dir_count++; | 4326 | processed_dir_count++; |
4244 | if (info.attribute & ATTR_DIRECTORY) | 4327 | if (info.attribute & ATTR_DIRECTORY) |
4245 | check_dir(curpath, add_files); | 4328 | { /* don't follow symlinks to dirs, but try to add it as a search root |
4329 | * this makes able to avoid looping in recursive symlinks */ | ||
4330 | if (info.attribute & ATTR_LINK) | ||
4331 | add_search_root(curpath); | ||
4332 | else | ||
4333 | check_dir(curpath, add_files); | ||
4334 | } | ||
4246 | else if (add_files) | 4335 | else if (add_files) |
4247 | { | 4336 | { |
4248 | tc_stat.curentry = curpath; | 4337 | tc_stat.curentry = curpath; |
@@ -4320,10 +4409,19 @@ void tagcache_build(const char *path) | |||
4320 | memset(&header, 0, sizeof(struct tagcache_header)); | 4409 | memset(&header, 0, sizeof(struct tagcache_header)); |
4321 | write(cachefd, &header, sizeof(struct tagcache_header)); | 4410 | write(cachefd, &header, sizeof(struct tagcache_header)); |
4322 | 4411 | ||
4323 | if (strcmp("/", path) != 0) | 4412 | ret = true; |
4324 | strcpy(curpath, path); | 4413 | roots_ll.path = path; |
4325 | ret = check_dir(path, true); | 4414 | roots_ll.next = NULL; |
4326 | 4415 | struct search_roots_ll * this; | |
4416 | /* check_dir might add new roots */ | ||
4417 | for(this = &roots_ll; this; this = this->next) | ||
4418 | { | ||
4419 | strcpy(curpath, this->path); | ||
4420 | ret = ret && check_dir(this->path, true); | ||
4421 | } | ||
4422 | if (roots_ll.next) | ||
4423 | free_search_roots(roots_ll.next); | ||
4424 | |||
4327 | /* Write the header. */ | 4425 | /* Write the header. */ |
4328 | header.magic = TAGCACHE_MAGIC; | 4426 | header.magic = TAGCACHE_MAGIC; |
4329 | header.datasize = data_size; | 4427 | header.datasize = data_size; |