xaizek / vifm (License: GPLv2+) (since 2018-12-07)
Vifm is a file manager with curses interface, which provides Vi[m]-like environment for managing objects within file systems, extended with some useful ideas from mutt.
Commit eb4cb0a8c0a5fdc8edbd2e072f9934df532216d7

Fix an issue with cache invalidation for dir links
Cache entries were stored with inode number of directory, but queried
with inode number of the symbolic link to it.
Author: xaizek
Author date (UTC): 2020-09-15 21:05
Committer name: xaizek
Committer date (UTC): 2020-09-15 21:05
Parent(s): 289416bd45e8294746abf73db99e91f0b27f6226
Signing key: 99DC5E4DB05F6BE2
Tree: 09fe56ea8acd7b15df73b29eb6329ed8ba603139
File Lines added Lines deleted
ChangeLog 3 0
src/filelist.c 2 6
src/status.c 1 4
src/utils/utils.h 4 0
src/utils/utils_nix.c 20 0
src/utils/utils_win.c 6 0
tests/misc/dcache.c 33 2
File ChangeLog changed (mode: 100644) (index 3f5d77335..07d457cb1)
5 5 Fixed ga and gA on symlinks to directories on their own (regression in Fixed ga and gA on symlinks to directories on their own (regression in
6 6 0.11-beta) and as part of selection. Thanks to filterfalse. 0.11-beta) and as part of selection. Thanks to filterfalse.
7 7
8 Fixed an issue with undesired cache invalidation for symbolic link to
9 directories, which caused performance issue (regression in 0.11-beta).
10
8 11 0.10.1 to 0.11-beta (2020-09-10) 0.10.1 to 0.11-beta (2020-09-10)
9 12
10 13 Added :VifmCs command to the plugin for "converting" Vim's color scheme Added :VifmCs command to the plugin for "converting" Vim's color scheme
File src/filelist.c changed (mode: 100644) (index f41ade678..5121fadd9)
... ... recalc_entry_size(const dir_entry_t *entry, uint64_t old_size)
1583 1583 static uint64_t static uint64_t
1584 1584 entry_calc_nitems(const dir_entry_t *entry) entry_calc_nitems(const dir_entry_t *entry)
1585 1585 { {
1586 uint64_t ret;
1587 1586 char full_path[PATH_MAX + 1]; char full_path[PATH_MAX + 1];
1588 1587 get_full_path_of(entry, sizeof(full_path), full_path); get_full_path_of(entry, sizeof(full_path), full_path);
1589 1588
1590 uint64_t inode = DCACHE_UNKNOWN;
1591 #ifndef _WIN32
1592 inode = entry->inode;
1593 #endif
1589 uint64_t ret = count_dir_items(full_path);
1594 1590
1595 ret = count_dir_items(full_path);
1591 uint64_t inode = get_true_inode(entry);
1596 1592 dcache_set_at(full_path, inode, DCACHE_UNKNOWN, ret); dcache_set_at(full_path, inode, DCACHE_UNKNOWN, ret);
1597 1593
1598 1594 return ret; return ret;
File src/status.c changed (mode: 100644) (index 26091e75f..1cfd9995f)
... ... dcache_get_of(const dir_entry_t *entry, dcache_result_t *size,
573 573 char full_path[PATH_MAX + 1]; char full_path[PATH_MAX + 1];
574 574 get_full_path_of(entry, sizeof(full_path), full_path); get_full_path_of(entry, sizeof(full_path), full_path);
575 575
576 uint64_t inode = 0;
577 #ifndef _WIN32
578 inode = entry->inode;
579 #endif
576 uint64_t inode = get_true_inode(entry);
580 577 dcache_get(full_path, entry->mtime, inode, size, nitems); dcache_get(full_path, entry->mtime, inode, size, nitems);
581 578 } }
582 579
File src/utils/utils.h changed (mode: 100644) (index b6e45d5a2..e405e2c80)
... ... void clone_attribs(const char path[], const char from[], const struct stat *st);
271 271 * amount in bytes. */ * amount in bytes. */
272 272 uint64_t get_free_space(const char at[]); uint64_t get_free_space(const char at[]);
273 273
274 /* Retrieves inode number that corresponds to the entry by resolving symbolic
275 * links if necessary. Returns the inode number. */
276 uint64_t get_true_inode(const struct dir_entry_t *entry);
277
274 278 #ifdef _WIN32 #ifdef _WIN32
275 279 #include "utils_win.h" #include "utils_win.h"
276 280 #else #else
File src/utils/utils_nix.c changed (mode: 100644) (index d23a237ea..cb6c176ee)
59 59 #include "../compat/reallocarray.h" #include "../compat/reallocarray.h"
60 60 #include "../ui/tabs.h" #include "../ui/tabs.h"
61 61 #include "../ui/ui.h" #include "../ui/ui.h"
62 #include "../filelist.h"
62 63 #include "../running.h" #include "../running.h"
63 64 #include "../status.h" #include "../status.h"
64 65 #include "cancellation.h" #include "cancellation.h"
 
... ... get_free_space(const char at[])
1160 1161 #endif #endif
1161 1162 } }
1162 1163
1164 uint64_t
1165 get_true_inode(const struct dir_entry_t *entry)
1166 {
1167 if(entry->type != FT_LINK)
1168 {
1169 return entry->inode;
1170 }
1171
1172 char full_path[PATH_MAX + 1];
1173 get_full_path_of(entry, sizeof(full_path), full_path);
1174
1175 struct stat s;
1176 if(os_stat(full_path, &s) == 0)
1177 {
1178 return s.st_ino;
1179 }
1180 return entry->inode;
1181 }
1182
1163 1183 /* vim: set tabstop=2 softtabstop=2 shiftwidth=2 noexpandtab cinoptions-=(0 : */ /* vim: set tabstop=2 softtabstop=2 shiftwidth=2 noexpandtab cinoptions-=(0 : */
1164 1184 /* vim: set cinoptions+=t0 filetype=c : */ /* vim: set cinoptions+=t0 filetype=c : */
File src/utils/utils_win.c changed (mode: 100644) (index 4430183a0..49a75b331)
... ... win_shortcut_read(const char shortcut[], char buf[], int buf_len)
1256 1256 return 1; return 1;
1257 1257 } }
1258 1258
1259 uint64_t
1260 get_true_inode(const struct dir_entry_t *entry)
1261 {
1262 return 0;
1263 }
1264
1259 1265 /* vim: set tabstop=2 softtabstop=2 shiftwidth=2 noexpandtab cinoptions-=(0 : */ /* vim: set tabstop=2 softtabstop=2 shiftwidth=2 noexpandtab cinoptions-=(0 : */
1260 1266 /* vim: set cinoptions+=t0 filetype=c : */ /* vim: set cinoptions+=t0 filetype=c : */
File tests/misc/dcache.c changed (mode: 100644) (index f5e56cd75..67ed8a983)
1 1 #include <stic.h> #include <stic.h>
2 2
3 #include <unistd.h> /* symlink() */
4
3 5 #include <stddef.h> /* NULL */ #include <stddef.h> /* NULL */
4 6 #include <string.h> /* memset() strcpy() */ #include <string.h> /* memset() strcpy() */
5 7 #include <time.h> /* time() */ #include <time.h> /* time() */
 
7 9 #include <test-utils.h> #include <test-utils.h>
8 10
9 11 #include "../../src/cfg/config.h" #include "../../src/cfg/config.h"
12 #include "../../src/compat/os.h"
10 13 #include "../../src/ui/ui.h" #include "../../src/ui/ui.h"
11 14 #include "../../src/utils/str.h" #include "../../src/utils/str.h"
12 15 #include "../../src/status.h" #include "../../src/status.h"
 
... ... TEST(outdated_data_is_detected)
74 77 TEST(can_query_one_parameter_at_a_time) TEST(can_query_one_parameter_at_a_time)
75 78 { {
76 79 dcache_result_t data; dcache_result_t data;
77 dir_entry_t entry = { .name = "read", .origin = TEST_DATA_PATH };
80 dir_entry_t entry = {
81 .name = "read", .origin = TEST_DATA_PATH, .type = FT_DIR
82 };
78 83
79 84 dcache_set_at(TEST_DATA_PATH "/read", 0, 10, 11); dcache_set_at(TEST_DATA_PATH "/read", 0, 10, 11);
80 85
 
... ... TEST(can_query_one_parameter_at_a_time)
89 94
90 95 #ifndef _WIN32 #ifndef _WIN32
91 96
97 TEST(symlink_inode_resolution, IF(not_windows))
98 {
99 dir_entry_t link_entry = {
100 .name = "link", .origin = SANDBOX_PATH, .type = FT_LINK,
101 };
102
103 create_dir(SANDBOX_PATH "/dir");
104
105 struct stat s;
106 assert_success(os_stat(SANDBOX_PATH "/dir", &s));
107
108 assert_success(symlink("dir", SANDBOX_PATH "/link"));
109
110 dcache_set_at(SANDBOX_PATH "/dir", s.st_ino, 10, DCACHE_UNKNOWN);
111
112 dcache_result_t data;
113 dcache_get_of(&link_entry, &data, NULL);
114 assert_true(data.is_valid);
115 assert_ulong_equal(10, data.value);
116
117 remove_file(SANDBOX_PATH "/link");
118 remove_dir(SANDBOX_PATH "/dir");
119 }
120
92 121 TEST(inode_is_taken_into_account) TEST(inode_is_taken_into_account)
93 122 { {
94 123 dcache_result_t size, nitems; dcache_result_t size, nitems;
95 124
96 dir_entry_t entry = { .name = "read", .origin = TEST_DATA_PATH, .inode = 1 };
125 dir_entry_t entry = {
126 .name = "read", .origin = TEST_DATA_PATH, .inode = 1, .type = FT_DIR
127 };
97 128
98 129 dcache_set_at(TEST_DATA_PATH "/read", 1, 10, 11); dcache_set_at(TEST_DATA_PATH "/read", 1, 10, 11);
99 130
Hints

Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/vifm

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/vifm

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master