diff options
author | Miika Pekkarinen <miipekk@ihme.org> | 2009-06-20 16:17:54 +0000 |
---|---|---|
committer | Miika Pekkarinen <miipekk@ihme.org> | 2009-06-20 16:17:54 +0000 |
commit | 8e2bdcaab6857daed1174487e4262d1a4c5db9ab (patch) | |
tree | 66441264df232454d909ca94bdfdc9a915842e59 /apps/tagcache.c | |
parent | d79d239382e53fc570cf49e8ea4b5150b42c906e (diff) | |
download | rockbox-8e2bdcaab6857daed1174487e4262d1a4c5db9ab.tar.gz rockbox-8e2bdcaab6857daed1174487e4262d1a4c5db9ab.zip |
A bunch of stability fixes into tagcache engine and database browser. Mainly data retrieval problems, races, data corruption of sorted index files at the end with junk data, access to unitialized memory and so on. Should fix FS#8710 and may fix FS#8414.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@21402 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/tagcache.c')
-rw-r--r-- | apps/tagcache.c | 214 |
1 files changed, 134 insertions, 80 deletions
diff --git a/apps/tagcache.c b/apps/tagcache.c index d4ec1078d8..d7a377e7e2 100644 --- a/apps/tagcache.c +++ b/apps/tagcache.c | |||
@@ -410,7 +410,7 @@ static long find_entry_ram(const char *filename, | |||
410 | } | 410 | } |
411 | #endif | 411 | #endif |
412 | 412 | ||
413 | static long find_entry_disk(const char *filename) | 413 | static long find_entry_disk(const char *filename, bool localfd) |
414 | { | 414 | { |
415 | struct tagcache_header tch; | 415 | struct tagcache_header tch; |
416 | static long last_pos = -1; | 416 | static long last_pos = -1; |
@@ -427,7 +427,7 @@ static long find_entry_disk(const char *filename) | |||
427 | return -2; | 427 | return -2; |
428 | 428 | ||
429 | fd = filenametag_fd; | 429 | fd = filenametag_fd; |
430 | if (fd < 0) | 430 | if (fd < 0 || localfd) |
431 | { | 431 | { |
432 | last_pos = -1; | 432 | last_pos = -1; |
433 | if ( (fd = open_tag_fd(&tch, tag_filename, false)) < 0) | 433 | if ( (fd = open_tag_fd(&tch, tag_filename, false)) < 0) |
@@ -458,6 +458,8 @@ static long find_entry_disk(const char *filename) | |||
458 | { | 458 | { |
459 | logf("too long tag #1"); | 459 | logf("too long tag #1"); |
460 | close(fd); | 460 | close(fd); |
461 | if (!localfd) | ||
462 | filenametag_fd = -1; | ||
461 | last_pos = -1; | 463 | last_pos = -1; |
462 | return -2; | 464 | return -2; |
463 | } | 465 | } |
@@ -466,6 +468,8 @@ static long find_entry_disk(const char *filename) | |||
466 | { | 468 | { |
467 | logf("read error #2"); | 469 | logf("read error #2"); |
468 | close(fd); | 470 | close(fd); |
471 | if (!localfd) | ||
472 | filenametag_fd = -1; | ||
469 | last_pos = -1; | 473 | last_pos = -1; |
470 | return -3; | 474 | return -3; |
471 | } | 475 | } |
@@ -491,12 +495,12 @@ static long find_entry_disk(const char *filename) | |||
491 | goto check_again; | 495 | goto check_again; |
492 | } | 496 | } |
493 | 497 | ||
494 | if (fd != filenametag_fd) | 498 | if (fd != filenametag_fd || localfd) |
495 | close(fd); | 499 | close(fd); |
496 | return -4; | 500 | return -4; |
497 | } | 501 | } |
498 | 502 | ||
499 | if (fd != filenametag_fd) | 503 | if (fd != filenametag_fd || localfd) |
500 | close(fd); | 504 | close(fd); |
501 | 505 | ||
502 | return tfe.idx_id; | 506 | return tfe.idx_id; |
@@ -512,7 +516,7 @@ static int find_index(const char *filename) | |||
512 | #endif | 516 | #endif |
513 | 517 | ||
514 | if (idx_id < 0) | 518 | if (idx_id < 0) |
515 | idx_id = find_entry_disk(filename); | 519 | idx_id = find_entry_disk(filename, true); |
516 | 520 | ||
517 | return idx_id; | 521 | return idx_id; |
518 | } | 522 | } |
@@ -554,8 +558,14 @@ static bool get_index(int masterfd, int idxid, | |||
554 | if (hdr->indices[idxid].flag & FLAG_DELETED) | 558 | if (hdr->indices[idxid].flag & FLAG_DELETED) |
555 | return false; | 559 | return false; |
556 | 560 | ||
557 | memcpy(idx, &hdr->indices[idxid], sizeof(struct index_entry)); | 561 | # ifdef HAVE_DIRCACHE |
558 | return true; | 562 | if (!(hdr->indices[idxid].flag & FLAG_DIRCACHE) |
563 | || is_dircache_intact()) | ||
564 | #endif | ||
565 | { | ||
566 | memcpy(idx, &hdr->indices[idxid], sizeof(struct index_entry)); | ||
567 | return true; | ||
568 | } | ||
559 | } | 569 | } |
560 | #else | 570 | #else |
561 | (void)use_ram; | 571 | (void)use_ram; |
@@ -1006,17 +1016,20 @@ static bool add_uniqbuf(struct tagcache_search *tcs, unsigned long id) | |||
1006 | static bool build_lookup_list(struct tagcache_search *tcs) | 1016 | static bool build_lookup_list(struct tagcache_search *tcs) |
1007 | { | 1017 | { |
1008 | struct index_entry entry; | 1018 | struct index_entry entry; |
1009 | int i; | 1019 | int i, j; |
1010 | 1020 | ||
1011 | tcs->seek_list_count = 0; | 1021 | tcs->seek_list_count = 0; |
1012 | 1022 | ||
1013 | #ifdef HAVE_TC_RAMCACHE | 1023 | #ifdef HAVE_TC_RAMCACHE |
1014 | if (tcs->ramsearch) | 1024 | if (tcs->ramsearch |
1025 | # ifdef HAVE_DIRCACHE | ||
1026 | && (tcs->type != tag_filename || is_dircache_intact()) | ||
1027 | # endif | ||
1028 | ) | ||
1015 | { | 1029 | { |
1016 | int j; | ||
1017 | |||
1018 | for (i = tcs->seek_pos; i < hdr->h.tch.entry_count; i++) | 1030 | for (i = tcs->seek_pos; i < hdr->h.tch.entry_count; i++) |
1019 | { | 1031 | { |
1032 | struct tagcache_seeklist_entry *seeklist; | ||
1020 | struct index_entry *idx = &hdr->indices[i]; | 1033 | struct index_entry *idx = &hdr->indices[i]; |
1021 | if (tcs->seek_list_count == SEEK_LIST_SIZE) | 1034 | if (tcs->seek_list_count == SEEK_LIST_SIZE) |
1022 | break ; | 1035 | break ; |
@@ -1046,26 +1059,37 @@ static bool build_lookup_list(struct tagcache_search *tcs) | |||
1046 | continue; | 1059 | continue; |
1047 | 1060 | ||
1048 | /* Lets add it. */ | 1061 | /* Lets add it. */ |
1049 | tcs->seek_list[tcs->seek_list_count] = idx->tag_seek[tcs->type]; | 1062 | seeklist = &tcs->seeklist[tcs->seek_list_count]; |
1050 | tcs->seek_flags[tcs->seek_list_count] = idx->flag; | 1063 | seeklist->seek = idx->tag_seek[tcs->type]; |
1064 | seeklist->flag = idx->flag; | ||
1065 | seeklist->idx_id = i; | ||
1051 | tcs->seek_list_count++; | 1066 | tcs->seek_list_count++; |
1052 | } | 1067 | } |
1053 | 1068 | ||
1054 | tcs->seek_pos = i; | 1069 | tcs->seek_pos = i; |
1055 | 1070 | ||
1056 | return tcs->seek_list_count > 0; | 1071 | return tcs->seek_list_count > 0; |
1057 | } | 1072 | } |
1058 | #endif | 1073 | #endif |
1059 | 1074 | ||
1075 | if (tcs->masterfd < 0) | ||
1076 | { | ||
1077 | struct master_header tcmh; | ||
1078 | tcs->masterfd = open_master_fd(&tcmh, false); | ||
1079 | } | ||
1080 | |||
1060 | lseek(tcs->masterfd, tcs->seek_pos * sizeof(struct index_entry) + | 1081 | lseek(tcs->masterfd, tcs->seek_pos * sizeof(struct index_entry) + |
1061 | sizeof(struct master_header), SEEK_SET); | 1082 | sizeof(struct master_header), SEEK_SET); |
1062 | 1083 | ||
1063 | while (ecread(tcs->masterfd, &entry, 1, index_entry_ec, tc_stat.econ) | 1084 | while (ecread(tcs->masterfd, &entry, 1, index_entry_ec, tc_stat.econ) |
1064 | == sizeof(struct index_entry)) | 1085 | == sizeof(struct index_entry)) |
1065 | { | 1086 | { |
1087 | struct tagcache_seeklist_entry *seeklist; | ||
1088 | |||
1066 | if (tcs->seek_list_count == SEEK_LIST_SIZE) | 1089 | if (tcs->seek_list_count == SEEK_LIST_SIZE) |
1067 | break ; | 1090 | break ; |
1068 | 1091 | ||
1092 | i = tcs->seek_pos; | ||
1069 | tcs->seek_pos++; | 1093 | tcs->seek_pos++; |
1070 | 1094 | ||
1071 | /* Check if entry has been deleted. */ | 1095 | /* Check if entry has been deleted. */ |
@@ -1073,13 +1097,13 @@ static bool build_lookup_list(struct tagcache_search *tcs) | |||
1073 | continue; | 1097 | continue; |
1074 | 1098 | ||
1075 | /* Go through all filters.. */ | 1099 | /* Go through all filters.. */ |
1076 | for (i = 0; i < tcs->filter_count; i++) | 1100 | for (j = 0; j < tcs->filter_count; j++) |
1077 | { | 1101 | { |
1078 | if (entry.tag_seek[tcs->filter_tag[i]] != tcs->filter_seek[i]) | 1102 | if (entry.tag_seek[tcs->filter_tag[j]] != tcs->filter_seek[j]) |
1079 | break ; | 1103 | break ; |
1080 | } | 1104 | } |
1081 | 1105 | ||
1082 | if (i < tcs->filter_count) | 1106 | if (j < tcs->filter_count) |
1083 | continue ; | 1107 | continue ; |
1084 | 1108 | ||
1085 | /* Check for conditions. */ | 1109 | /* Check for conditions. */ |
@@ -1091,8 +1115,10 @@ static bool build_lookup_list(struct tagcache_search *tcs) | |||
1091 | continue; | 1115 | continue; |
1092 | 1116 | ||
1093 | /* Lets add it. */ | 1117 | /* Lets add it. */ |
1094 | tcs->seek_list[tcs->seek_list_count] = entry.tag_seek[tcs->type]; | 1118 | seeklist = &tcs->seeklist[tcs->seek_list_count]; |
1095 | tcs->seek_flags[tcs->seek_list_count] = entry.flag; | 1119 | seeklist->seek = entry.tag_seek[tcs->type]; |
1120 | seeklist->flag = entry.flag; | ||
1121 | seeklist->idx_id = i; | ||
1096 | tcs->seek_list_count++; | 1122 | tcs->seek_list_count++; |
1097 | 1123 | ||
1098 | yield(); | 1124 | yield(); |
@@ -1155,15 +1181,17 @@ static bool check_all_headers(void) | |||
1155 | return true; | 1181 | return true; |
1156 | } | 1182 | } |
1157 | 1183 | ||
1184 | bool tagcache_is_busy(void) | ||
1185 | { | ||
1186 | return read_lock || write_lock; | ||
1187 | } | ||
1188 | |||
1158 | bool tagcache_search(struct tagcache_search *tcs, int tag) | 1189 | bool tagcache_search(struct tagcache_search *tcs, int tag) |
1159 | { | 1190 | { |
1160 | struct tagcache_header tag_hdr; | 1191 | struct tagcache_header tag_hdr; |
1161 | struct master_header master_hdr; | 1192 | struct master_header master_hdr; |
1162 | int i; | 1193 | int i; |
1163 | 1194 | ||
1164 | if (tcs->initialized) | ||
1165 | tagcache_search_finish(tcs); | ||
1166 | |||
1167 | while (read_lock) | 1195 | while (read_lock) |
1168 | sleep(1); | 1196 | sleep(1); |
1169 | 1197 | ||
@@ -1174,6 +1202,7 @@ bool tagcache_search(struct tagcache_search *tcs, int tag) | |||
1174 | tcs->position = sizeof(struct tagcache_header); | 1202 | tcs->position = sizeof(struct tagcache_header); |
1175 | tcs->type = tag; | 1203 | tcs->type = tag; |
1176 | tcs->seek_pos = 0; | 1204 | tcs->seek_pos = 0; |
1205 | tcs->list_position = 0; | ||
1177 | tcs->seek_list_count = 0; | 1206 | tcs->seek_list_count = 0; |
1178 | tcs->filter_count = 0; | 1207 | tcs->filter_count = 0; |
1179 | tcs->masterfd = -1; | 1208 | tcs->masterfd = -1; |
@@ -1192,19 +1221,24 @@ bool tagcache_search(struct tagcache_search *tcs, int tag) | |||
1192 | else | 1221 | else |
1193 | #endif | 1222 | #endif |
1194 | { | 1223 | { |
1224 | /* Always open as R/W so we can pass tcs to functions that modify data also | ||
1225 | * without failing. */ | ||
1226 | tcs->masterfd = open_master_fd(&master_hdr, true); | ||
1227 | if (tcs->masterfd < 0) | ||
1228 | return false; | ||
1229 | |||
1195 | if (!TAGCACHE_IS_NUMERIC(tcs->type)) | 1230 | if (!TAGCACHE_IS_NUMERIC(tcs->type)) |
1196 | { | 1231 | { |
1197 | tcs->idxfd[tcs->type] = open_tag_fd(&tag_hdr, tcs->type, false); | 1232 | tcs->idxfd[tcs->type] = open_tag_fd(&tag_hdr, tcs->type, false); |
1198 | if (tcs->idxfd[tcs->type] < 0) | 1233 | if (tcs->idxfd[tcs->type] < 0) |
1199 | return false; | 1234 | return false; |
1235 | |||
1236 | tcs->entry_count = tag_hdr.entry_count; | ||
1237 | } | ||
1238 | else | ||
1239 | { | ||
1240 | tcs->entry_count = master_hdr.tch.entry_count; | ||
1200 | } | 1241 | } |
1201 | |||
1202 | /* Always open as R/W so we can pass tcs to functions that modify data also | ||
1203 | * without failing. */ | ||
1204 | tcs->masterfd = open_master_fd(&master_hdr, true); | ||
1205 | |||
1206 | if (tcs->masterfd < 0) | ||
1207 | return false; | ||
1208 | } | 1242 | } |
1209 | 1243 | ||
1210 | tcs->valid = true; | 1244 | tcs->valid = true; |
@@ -1272,14 +1306,6 @@ bool tagcache_search_add_clause(struct tagcache_search *tcs, | |||
1272 | return true; | 1306 | return true; |
1273 | } | 1307 | } |
1274 | 1308 | ||
1275 | /* TODO: Remove this mess. */ | ||
1276 | #ifdef HAVE_DIRCACHE | ||
1277 | #define TAG_FILENAME_RAM(tcs) ((tcs->type == tag_filename) \ | ||
1278 | ? ((flag & FLAG_DIRCACHE) && is_dircache_intact()) : 1) | ||
1279 | #else | ||
1280 | #define TAG_FILENAME_RAM(tcs) (tcs->type != tag_filename) | ||
1281 | #endif | ||
1282 | |||
1283 | static bool get_next(struct tagcache_search *tcs) | 1309 | static bool get_next(struct tagcache_search *tcs) |
1284 | { | 1310 | { |
1285 | static char buf[TAG_MAXLEN+32]; | 1311 | static char buf[TAG_MAXLEN+32]; |
@@ -1298,11 +1324,20 @@ static bool get_next(struct tagcache_search *tcs) | |||
1298 | 1324 | ||
1299 | /* Relative fetch. */ | 1325 | /* Relative fetch. */ |
1300 | if (tcs->filter_count > 0 || tcs->clause_count > 0 | 1326 | if (tcs->filter_count > 0 || tcs->clause_count > 0 |
1301 | || TAGCACHE_IS_NUMERIC(tcs->type)) | 1327 | || TAGCACHE_IS_NUMERIC(tcs->type) |
1328 | #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE) | ||
1329 | /* We need to retrieve flag status for dircache. */ | ||
1330 | || (tcs->ramsearch && tcs->type == tag_filename) | ||
1331 | #endif | ||
1332 | ) | ||
1302 | { | 1333 | { |
1334 | struct tagcache_seeklist_entry *seeklist; | ||
1335 | |||
1303 | /* Check for end of list. */ | 1336 | /* Check for end of list. */ |
1304 | if (tcs->seek_list_count == 0) | 1337 | if (tcs->list_position == tcs->seek_list_count) |
1305 | { | 1338 | { |
1339 | tcs->list_position = 0; | ||
1340 | |||
1306 | /* Try to fetch more. */ | 1341 | /* Try to fetch more. */ |
1307 | if (!build_lookup_list(tcs)) | 1342 | if (!build_lookup_list(tcs)) |
1308 | { | 1343 | { |
@@ -1311,15 +1346,28 @@ static bool get_next(struct tagcache_search *tcs) | |||
1311 | } | 1346 | } |
1312 | } | 1347 | } |
1313 | 1348 | ||
1314 | tcs->seek_list_count--; | 1349 | seeklist = &tcs->seeklist[tcs->list_position]; |
1315 | flag = tcs->seek_flags[tcs->seek_list_count]; | 1350 | flag = seeklist->flag; |
1316 | tcs->position = tcs->seek_list[tcs->seek_list_count]; | 1351 | tcs->position = seeklist->seek; |
1352 | tcs->idx_id = seeklist->idx_id; | ||
1353 | tcs->list_position++; | ||
1317 | } | 1354 | } |
1355 | else | ||
1356 | { | ||
1357 | if (tcs->entry_count == 0) | ||
1358 | { | ||
1359 | tcs->valid = false; | ||
1360 | return false; | ||
1361 | } | ||
1362 | |||
1363 | tcs->entry_count--; | ||
1364 | } | ||
1365 | |||
1366 | tcs->result_seek = tcs->position; | ||
1318 | 1367 | ||
1319 | if (TAGCACHE_IS_NUMERIC(tcs->type)) | 1368 | if (TAGCACHE_IS_NUMERIC(tcs->type)) |
1320 | { | 1369 | { |
1321 | snprintf(buf, sizeof(buf), "%d", tcs->position); | 1370 | snprintf(buf, sizeof(buf), "%d", tcs->position); |
1322 | tcs->result_seek = tcs->position; | ||
1323 | tcs->result = buf; | 1371 | tcs->result = buf; |
1324 | tcs->result_len = strlen(buf) + 1; | 1372 | tcs->result_len = strlen(buf) + 1; |
1325 | return true; | 1373 | return true; |
@@ -1327,55 +1375,54 @@ static bool get_next(struct tagcache_search *tcs) | |||
1327 | 1375 | ||
1328 | /* Direct fetch. */ | 1376 | /* Direct fetch. */ |
1329 | #ifdef HAVE_TC_RAMCACHE | 1377 | #ifdef HAVE_TC_RAMCACHE |
1330 | if (tcs->ramsearch && TAG_FILENAME_RAM(tcs)) | 1378 | if (tcs->ramsearch) |
1331 | { | 1379 | { |
1332 | struct tagfile_entry *ep; | ||
1333 | |||
1334 | if (tcs->entry_count == 0) | ||
1335 | { | ||
1336 | tcs->valid = false; | ||
1337 | return false; | ||
1338 | } | ||
1339 | tcs->entry_count--; | ||
1340 | 1380 | ||
1341 | tcs->result_seek = tcs->position; | 1381 | #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE) |
1342 | 1382 | if (tcs->type == tag_filename && (flag & FLAG_DIRCACHE) | |
1343 | # ifdef HAVE_DIRCACHE | 1383 | && is_dircache_intact()) |
1344 | if (tcs->type == tag_filename) | ||
1345 | { | 1384 | { |
1346 | dircache_copy_path((struct dirent *)tcs->position, | 1385 | dircache_copy_path((struct dirent *)tcs->position, |
1347 | buf, sizeof buf); | 1386 | buf, sizeof buf); |
1348 | tcs->result = buf; | 1387 | tcs->result = buf; |
1349 | tcs->result_len = strlen(buf) + 1; | 1388 | tcs->result_len = strlen(buf) + 1; |
1350 | tcs->idx_id = FLAG_GET_ATTR(flag); | ||
1351 | tcs->ramresult = false; | 1389 | tcs->ramresult = false; |
1352 | 1390 | ||
1353 | return true; | 1391 | return true; |
1354 | } | 1392 | } |
1355 | # endif | 1393 | else |
1356 | 1394 | #endif | |
1357 | ep = (struct tagfile_entry *)&hdr->tags[tcs->type][tcs->position]; | 1395 | if (tcs->type != tag_filename) |
1358 | tcs->position += sizeof(struct tagfile_entry) + ep->tag_length; | 1396 | { |
1359 | tcs->result = ep->tag_data; | 1397 | struct tagfile_entry *ep; |
1360 | tcs->result_len = strlen(tcs->result) + 1; | 1398 | |
1361 | tcs->idx_id = ep->idx_id; | 1399 | ep = (struct tagfile_entry *)&hdr->tags[tcs->type][tcs->position]; |
1362 | tcs->ramresult = true; | 1400 | tcs->result = ep->tag_data; |
1363 | 1401 | tcs->result_len = strlen(tcs->result) + 1; | |
1364 | return true; | 1402 | tcs->idx_id = ep->idx_id; |
1403 | tcs->ramresult = true; | ||
1404 | |||
1405 | /* Increase position for the next run. This may get overwritten. */ | ||
1406 | tcs->position += sizeof(struct tagfile_entry) + ep->tag_length; | ||
1407 | |||
1408 | return true; | ||
1409 | } | ||
1365 | } | 1410 | } |
1366 | #endif | 1411 | #endif |
1367 | 1412 | ||
1368 | if (!open_files(tcs, tcs->type)) | 1413 | if (!open_files(tcs, tcs->type)) |
1414 | { | ||
1415 | tcs->valid = false; | ||
1369 | return false; | 1416 | return false; |
1417 | } | ||
1370 | 1418 | ||
1371 | /* Seek stream to the correct position and continue to direct fetch. */ | 1419 | /* Seek stream to the correct position and continue to direct fetch. */ |
1372 | lseek(tcs->idxfd[tcs->type], tcs->position, SEEK_SET); | 1420 | lseek(tcs->idxfd[tcs->type], tcs->position, SEEK_SET); |
1373 | tcs->result_seek = tcs->position; | ||
1374 | 1421 | ||
1375 | if (ecread(tcs->idxfd[tcs->type], &entry, 1, | 1422 | if (ecread(tcs->idxfd[tcs->type], &entry, 1, |
1376 | tagfile_entry_ec, tc_stat.econ) != sizeof(struct tagfile_entry)) | 1423 | tagfile_entry_ec, tc_stat.econ) != sizeof(struct tagfile_entry)) |
1377 | { | 1424 | { |
1378 | /* End of data. */ | 1425 | logf("read error #5"); |
1379 | tcs->valid = false; | 1426 | tcs->valid = false; |
1380 | return false; | 1427 | return false; |
1381 | } | 1428 | } |
@@ -1384,6 +1431,7 @@ static bool get_next(struct tagcache_search *tcs) | |||
1384 | { | 1431 | { |
1385 | tcs->valid = false; | 1432 | tcs->valid = false; |
1386 | logf("too long tag #2"); | 1433 | logf("too long tag #2"); |
1434 | logf("P:%X/%X", tcs->position, entry.tag_length); | ||
1387 | return false; | 1435 | return false; |
1388 | } | 1436 | } |
1389 | 1437 | ||
@@ -1536,12 +1584,12 @@ bool tagcache_fill_tags(struct mp3entry *id3, const char *filename) | |||
1536 | struct index_entry *entry; | 1584 | struct index_entry *entry; |
1537 | int idx_id; | 1585 | int idx_id; |
1538 | 1586 | ||
1539 | if (!tc_stat.ready) | 1587 | if (!tc_stat.ready || !tc_stat.ramcache) |
1540 | return false; | 1588 | return false; |
1541 | 1589 | ||
1542 | /* Find the corresponding entry in tagcache. */ | 1590 | /* Find the corresponding entry in tagcache. */ |
1543 | idx_id = find_entry_ram(filename, NULL); | 1591 | idx_id = find_entry_ram(filename, NULL); |
1544 | if (idx_id < 0 || !tc_stat.ramcache) | 1592 | if (idx_id < 0) |
1545 | return false; | 1593 | return false; |
1546 | 1594 | ||
1547 | entry = &hdr->indices[idx_id]; | 1595 | entry = &hdr->indices[idx_id]; |
@@ -1644,14 +1692,11 @@ static void add_tagcache(char *path, unsigned long mtime | |||
1644 | { | 1692 | { |
1645 | idx_id = find_entry_ram(path, dc); | 1693 | idx_id = find_entry_ram(path, dc); |
1646 | } | 1694 | } |
1647 | else | ||
1648 | #endif | 1695 | #endif |
1649 | { | 1696 | |
1650 | if (filenametag_fd >= 0) | 1697 | /* Be sure the entry doesn't exist. */ |
1651 | { | 1698 | if (filenametag_fd >= 0 && idx_id < 0) |
1652 | idx_id = find_entry_disk(path); | 1699 | idx_id = find_entry_disk(path, false); |
1653 | } | ||
1654 | } | ||
1655 | 1700 | ||
1656 | /* Check if file has been modified. */ | 1701 | /* Check if file has been modified. */ |
1657 | if (idx_id >= 0) | 1702 | if (idx_id >= 0) |
@@ -2548,6 +2593,13 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd) | |||
2548 | 2593 | ||
2549 | /* Sort the buffer data and write it to the index file. */ | 2594 | /* Sort the buffer data and write it to the index file. */ |
2550 | lseek(fd, sizeof(struct tagcache_header), SEEK_SET); | 2595 | lseek(fd, sizeof(struct tagcache_header), SEEK_SET); |
2596 | /** | ||
2597 | * We need to truncate the index file now. There can be junk left | ||
2598 | * at the end of file (however, we _should_ always follow the | ||
2599 | * entry_count and don't crash with that). | ||
2600 | */ | ||
2601 | ftruncate(fd, lseek(fd, 0, SEEK_CUR)); | ||
2602 | |||
2551 | i = tempbuf_sort(fd); | 2603 | i = tempbuf_sort(fd); |
2552 | if (i < 0) | 2604 | if (i < 0) |
2553 | goto error_exit; | 2605 | goto error_exit; |
@@ -3328,7 +3380,10 @@ bool tagcache_import_changelog(void) | |||
3328 | close(masterfd); | 3380 | close(masterfd); |
3329 | 3381 | ||
3330 | if (filenametag_fd >= 0) | 3382 | if (filenametag_fd >= 0) |
3383 | { | ||
3331 | close(filenametag_fd); | 3384 | close(filenametag_fd); |
3385 | filenametag_fd = -1; | ||
3386 | } | ||
3332 | 3387 | ||
3333 | write_lock--; | 3388 | write_lock--; |
3334 | 3389 | ||
@@ -3919,7 +3974,6 @@ static bool load_tagcache(void) | |||
3919 | } | 3974 | } |
3920 | 3975 | ||
3921 | idx->flag |= FLAG_DIRCACHE; | 3976 | idx->flag |= FLAG_DIRCACHE; |
3922 | FLAG_SET_ATTR(idx->flag, fe->idx_id); | ||
3923 | idx->tag_seek[tag_filename] = (long)dc; | 3977 | idx->tag_seek[tag_filename] = (long)dc; |
3924 | } | 3978 | } |
3925 | else | 3979 | else |