summaryrefslogtreecommitdiff
path: root/apps/tagcache.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/tagcache.c')
-rw-r--r--apps/tagcache.c130
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
4196static 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 **/
4213static 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
4263static 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
4193static bool check_dir(const char *dirname, int add_files) 4279static 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;