summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Wilgus <wilgus.william@gmail.com>2021-10-13 23:45:00 -0400
committerWilliam Wilgus <wilgus.william@gmail.com>2021-10-16 10:18:44 -0400
commit15ee7400609b0b8837982a2dd388531bc19c06f6 (patch)
treea6a91ef67057533e61ed718e06863a55a88543c7
parent6fb942d8ff843444cbade57278de6e6687337fd6 (diff)
downloadrockbox-15ee7400609b0b8837982a2dd388531bc19c06f6.tar.gz
rockbox-15ee7400609b0b8837982a2dd388531bc19c06f6.zip
Open Plugins search by langids
On language change Stored plugins may fail to run due to hashing on lang dependent string allows searching by langid when the supplied key is LANG_PTR Fixes error on hash flush where previous entry was not restored Adds routine to update file in-place (for ATA targets) Other targets make a temp file to copy entries breaking changes: ROCKBOXDIR is no longer hashed since /.rockbox directory may soon be able to be changed packed attribute added to op data structure -- oops Change-Id: Ieead26609559b9c5bdadc6a95227cb2bfbb9f71c
-rw-r--r--apps/open_plugin.c282
-rw-r--r--apps/open_plugin.h13
-rw-r--r--apps/root_menu.c3
3 files changed, 215 insertions, 83 deletions
diff --git a/apps/open_plugin.c b/apps/open_plugin.c
index 7b5513a92b..32b5195334 100644
--- a/apps/open_plugin.c
+++ b/apps/open_plugin.c
@@ -27,6 +27,10 @@
27#include "splash.h" 27#include "splash.h"
28#include "lang.h" 28#include "lang.h"
29 29
30/* Define LOGF_ENABLE to enable logf output in this file */
31//#define LOGF_ENABLE
32#include "logf.h"
33
30#define ROCK_EXT "rock" 34#define ROCK_EXT "rock"
31#define ROCK_LEN 5 35#define ROCK_LEN 5
32#define OP_EXT "opx" 36#define OP_EXT "opx"
@@ -40,47 +44,132 @@ static int open_plugin_hash_get_entry(uint32_t hash,
40 struct open_plugin_entry_t *entry, 44 struct open_plugin_entry_t *entry,
41 const char* dat_file); 45 const char* dat_file);
42 46
47static const char* strip_rockbox_root(const char *path)
48{
49 int dlen = strlen(ROCKBOX_DIR);
50 if (strncmp(path, ROCKBOX_DIR, dlen) == 0)
51 path+= dlen;
52 return path;
53}
54
43static inline void op_clear_entry(struct open_plugin_entry_t *entry) 55static inline void op_clear_entry(struct open_plugin_entry_t *entry)
44{ 56{
45 if (entry) 57 if (entry == NULL)
58 return;
59 memset(entry, 0, op_entry_sz);
60 entry->lang_id = -1;
61}
62
63static int op_find_entry(int fd, struct open_plugin_entry_t *entry,
64 uint32_t hash, int32_t lang_id)
65{
66 int ret = OPEN_PLUGIN_NOT_FOUND;
67 int record = -1;
68 if (fd >= 0 && entry != NULL)
46 { 69 {
47 memset(entry, 0, op_entry_sz); 70 logf("OP find_entry *Searching* hash: %x lang_id: %d", hash, lang_id);
48 entry->lang_id = -1; 71 while (read(fd, entry, op_entry_sz) == op_entry_sz)
72 {
73 record++;
74 if (entry->lang_id == lang_id ||
75 (entry->hash == hash && hash != 0) ||
76 (lang_id == OPEN_PLUGIN_LANG_IGNOREALL))/* return first entry found */
77 {
78 /* NULL terminate fields NOTE -- all are actually +1 larger */
79 entry->name[OPEN_PLUGIN_NAMESZ] = '\0';
80 /*entry->key[OPEN_PLUGIN_BUFSZ] = '\0';*/
81 entry->path[OPEN_PLUGIN_BUFSZ] = '\0';
82 entry->param[OPEN_PLUGIN_BUFSZ] = '\0';
83 ret = record;
84 logf("OP find_entry *Found* hash: %x lang_id: %d",
85 entry->hash, entry->lang_id);
86 logf("OP find_entry rec: %d name: %s %s %s", record,
87 entry->name, entry->path, entry->param);
88 break;
89 }
90 }
49 } 91 }
92 return ret;
50} 93}
51 94
52static int op_update_dat(struct open_plugin_entry_t *entry, bool clear) 95static int op_update_dat(struct open_plugin_entry_t *entry, bool clear)
53{ 96{
54 int fd, fd1; 97 int fd;
55 uint32_t hash; 98 uint32_t hash;
56 99 int32_t lang_id;
57 if (!entry || entry->hash == 0) 100 if (!entry || entry->hash == 0)
58 return -1; 101 {
102 logf("OP update *No entry*");
103 return OPEN_PLUGIN_NOT_FOUND;
104 }
59 105
60 hash = entry->hash; 106 hash = entry->hash;
107 lang_id = entry->lang_id;
108 if (lang_id <= OPEN_PLUGIN_LANG_INVALID)
109 lang_id = OPEN_PLUGIN_LANG_IGNORE;
110
111 logf("OP update hash: %x lang_id: %d", hash, lang_id);
112 logf("OP update name: %s clear: %d", entry->name, (int) clear);
113 logf("OP update %s %s %s", entry->name, entry->path, entry->param);
114#if (CONFIG_STORAGE & STORAGE_ATA) /* Harddrive -- update existing */
115 logf("OP update *Updating entries* %s", OPEN_PLUGIN_DAT);
116 fd = open(OPEN_PLUGIN_DAT, O_RDWR | O_CREAT, 0666);
61 117
62 fd = open(OPEN_PLUGIN_DAT ".tmp", O_WRONLY | O_CREAT | O_TRUNC, 0666);
63 if (fd < 0) 118 if (fd < 0)
64 return -1; 119 return OPEN_PLUGIN_NOT_FOUND;
120 /* Only read the hash and lang id */
121 uint32_t hash_langid[2] = {0};
122 while (read(fd, &hash_langid, sizeof(hash_langid)) == sizeof(hash_langid))
123 {
124 if (hash_langid[0] == hash || (int32_t)hash_langid[1] == lang_id)
125 {
126 logf("OP update *Entry Exists* hash: %x langid: %d",
127 hash_langid[0], (int32_t)hash_langid[1]);
128 lseek(fd, 0-sizeof(hash_langid), SEEK_CUR);/* back to the start of record */
129 break;
130 }
131 lseek(fd, op_entry_sz - sizeof(hash_langid), SEEK_CUR); /* finish record */
132 }
65 write(fd, entry, op_entry_sz); 133 write(fd, entry, op_entry_sz);
134 close(fd);
135#else /* Everyone else make a temp file */
136 logf("OP update *Copying entries* %s", OPEN_PLUGIN_DAT ".tmp");
137 fd = open(OPEN_PLUGIN_DAT ".tmp", O_RDWR | O_CREAT | O_TRUNC, 0666);
66 138
67 fd1 = open(OPEN_PLUGIN_DAT, O_RDONLY); 139 if (fd < 0)
140 return OPEN_PLUGIN_NOT_FOUND;
141 write(fd, entry, op_entry_sz);
142
143 int fd1 = open(OPEN_PLUGIN_DAT, O_RDONLY);
68 if (fd1 >= 0) 144 if (fd1 >= 0)
69 { 145 {
70 while (read(fd1, &open_plugin_entry, op_entry_sz) == op_entry_sz) 146 /* copy non-duplicate entries back from original */
147 while (read(fd1, entry, op_entry_sz) == op_entry_sz)
71 { 148 {
72 if (open_plugin_entry.hash != hash) 149 if (entry->hash != hash && entry->lang_id != lang_id)
73 write(fd, &open_plugin_entry, op_entry_sz); 150 {
151 write(fd, entry, op_entry_sz);
152 }
74 } 153 }
75 close(fd1); 154 close(fd1);
76 remove(OPEN_PLUGIN_DAT); 155 remove(OPEN_PLUGIN_DAT);
77 } 156 }
157 if (!clear) /* retrieve original entry */
158 {
159 logf("OP update *Loading original entry*");
160 lseek(fd, 0, SEEK_SET);
161 int opret = op_find_entry(fd, entry, hash, lang_id);
162 clear = (opret == OPEN_PLUGIN_NOT_FOUND);
163 }
78 close(fd); 164 close(fd);
79
80 rename(OPEN_PLUGIN_DAT ".tmp", OPEN_PLUGIN_DAT); 165 rename(OPEN_PLUGIN_DAT ".tmp", OPEN_PLUGIN_DAT);
166#endif
81 167
82 if (clear) 168 if (clear)
83 op_clear_entry(&open_plugin_entry); 169 {
170 logf("OP update *Clearing entry*");
171 op_clear_entry(entry);
172 }
84 173
85 return 0; 174 return 0;
86} 175}
@@ -88,31 +177,33 @@ static int op_update_dat(struct open_plugin_entry_t *entry, bool clear)
88uint32_t open_plugin_add_path(const char *key, const char *plugin, const char *parameter) 177uint32_t open_plugin_add_path(const char *key, const char *plugin, const char *parameter)
89{ 178{
90 int len; 179 int len;
91 bool is_valid = false;
92 uint32_t hash; 180 uint32_t hash;
93 int32_t lang_id; 181 int32_t lang_id;
94 char *pos = "\0"; 182 char *pos = "\0";
95 183
96 if(!key) 184 if(!key)
97 { 185 {
186 logf("OP add_path No Key, *Clearing entry*");
98 op_clear_entry(&open_plugin_entry); 187 op_clear_entry(&open_plugin_entry);
99 return 0; 188 return 0;
100 } 189 }
101 190
102 lang_id = P2ID((unsigned char*)key); 191 lang_id = P2ID((unsigned char*)key);
103 key = P2STR((unsigned char *)key); 192 const char *skey = P2STR((unsigned char *)key);
104 193 logf("OP add_path key: %s lang id: %d", skey, lang_id);
105 open_plugin_get_hash(key, &hash); 194 open_plugin_get_hash(strip_rockbox_root(skey), &hash);
106
107 195
108 if(open_plugin_entry.hash != hash) 196 if(open_plugin_entry.hash != hash)
109 { 197 {
198 logf("OP add_path *Flush entry*");
110 /* the entry in ram needs saved */ 199 /* the entry in ram needs saved */
111 op_update_dat(&open_plugin_entry, true); 200 op_update_dat(&open_plugin_entry, true);
112 } 201 }
113 202
114 if (plugin) 203 if (plugin)
115 { 204 {
205 open_plugin_entry.hash = hash;
206 open_plugin_entry.lang_id = lang_id;
116 /* name */ 207 /* name */
117 if (path_basename(plugin, (const char **)&pos) == 0) 208 if (path_basename(plugin, (const char **)&pos) == 0)
118 pos = "\0"; 209 pos = "\0";
@@ -120,45 +211,46 @@ uint32_t open_plugin_add_path(const char *key, const char *plugin, const char *p
120 len = strlcpy(open_plugin_entry.name, pos, OPEN_PLUGIN_NAMESZ); 211 len = strlcpy(open_plugin_entry.name, pos, OPEN_PLUGIN_NAMESZ);
121 if (len > ROCK_LEN && strcasecmp(&(pos[len-ROCK_LEN]), "." ROCK_EXT) == 0) 212 if (len > ROCK_LEN && strcasecmp(&(pos[len-ROCK_LEN]), "." ROCK_EXT) == 0)
122 { 213 {
123 is_valid = true;
124
125 /* path */ 214 /* path */
126 strlcpy(open_plugin_entry.path, plugin, OPEN_PLUGIN_BUFSZ); 215 strlcpy(open_plugin_entry.path, plugin, OPEN_PLUGIN_BUFSZ);
127 216
128 if(parameter) 217 if(!parameter)
129 strlcpy(open_plugin_entry.param, parameter, OPEN_PLUGIN_BUFSZ); 218 parameter = "";
130 else 219 strlcpy(open_plugin_entry.param, parameter, OPEN_PLUGIN_BUFSZ);
131 open_plugin_entry.param[0] = '\0'; 220 goto retnhash;
132 } 221 }
133 else if (len > OP_LEN && strcasecmp(&(pos[len-OP_LEN]), "." OP_EXT) == 0) 222 else if (len > OP_LEN && strcasecmp(&(pos[len-OP_LEN]), "." OP_EXT) == 0)
134 { 223 {
135 is_valid = true;
136 open_plugin_hash_get_entry(0, &open_plugin_entry, plugin); 224 open_plugin_hash_get_entry(0, &open_plugin_entry, plugin);
225 goto retnhash;
137 } 226 }
138 } 227 }
139 228
140 if (!is_valid) 229 logf("OP add_path Invalid, *Clearing entry*");
141 { 230 if (lang_id != LANG_SHORTCUTS) /* from shortcuts menu */
142 if (lang_id != LANG_SHORTCUTS) /* from shortcuts menu */ 231 splashf(HZ * 2, str(LANG_OPEN_PLUGIN_NOT_A_PLUGIN), pos);
143 splashf(HZ / 2, str(LANG_OPEN_PLUGIN_NOT_A_PLUGIN), pos); 232 op_clear_entry(&open_plugin_entry);
144 op_clear_entry(&open_plugin_entry); 233 hash = 0;
145 hash = 0; 234
146 } 235retnhash:
147 else 236 logf("OP add_path name: %s %s %s",
148 { 237 open_plugin_entry.name,
149 open_plugin_entry.hash = hash; 238 open_plugin_entry.path,
150 open_plugin_entry.lang_id = lang_id; 239 open_plugin_entry.param);
151 }
152
153 return hash; 240 return hash;
154} 241}
155 242
156void open_plugin_browse(const char *key) 243void open_plugin_browse(const char *key)
157{ 244{
245 logf("OP Browse");
158 struct browse_context browse; 246 struct browse_context browse;
159 char tmp_buf[OPEN_PLUGIN_BUFSZ+1]; 247 char tmp_buf[OPEN_PLUGIN_BUFSZ+1];
160 open_plugin_get_entry(key, &open_plugin_entry); 248 open_plugin_get_entry(key, &open_plugin_entry);
161 249
250 logf("OP browse key: %s name: %s",
251 (key ? P2STR((unsigned char *)key):"No Key") ,open_plugin_entry.name);
252 logf("OP browse %s %s", open_plugin_entry.path, open_plugin_entry.param);
253
162 if (open_plugin_entry.path[0] == '\0') 254 if (open_plugin_entry.path[0] == '\0')
163 strcpy(open_plugin_entry.path, PLUGIN_DIR"/"); 255 strcpy(open_plugin_entry.path, PLUGIN_DIR"/");
164 256
@@ -172,78 +264,105 @@ void open_plugin_browse(const char *key)
172 open_plugin_add_path(key, tmp_buf, NULL); 264 open_plugin_add_path(key, tmp_buf, NULL);
173} 265}
174 266
175static int open_plugin_hash_get_entry(uint32_t hash, 267 static int op_get_entry(uint32_t hash, int32_t lang_id,
176 struct open_plugin_entry_t *entry, 268 struct open_plugin_entry_t *entry, const char *dat_file)
177 const char* dat_file)
178{ 269{
179 int ret = -1, record = -1; 270 int opret = OPEN_PLUGIN_NOT_FOUND;
180 271
181 if (entry) 272 if (entry)
182 { 273 {
274 /* Is the entry we want already loaded? */
275 if(hash != 0 && entry->hash == hash)
276 return OPEN_PLUGIN_NEEDS_FLUSHED;
183 277
184 if (hash != 0) 278 if(lang_id <= OPEN_PLUGIN_LANG_INVALID)
185 { 279 {
186 if(entry->hash == hash) /* hasn't been flushed yet? */ 280 lang_id = OPEN_PLUGIN_LANG_IGNORE;
187 return -2; 281 if (hash == 0)/* no hash or langid -- returns first entry found */
188 else 282 lang_id = OPEN_PLUGIN_LANG_IGNOREALL;
189 op_update_dat(&open_plugin_entry, true);
190 } 283 }
284 else if(entry->lang_id == lang_id)
285 {
286 return OPEN_PLUGIN_NEEDS_FLUSHED;
287 }
288
289 /* if another entry is loaded; flush it to disk before we destroy it */
290 op_update_dat(&open_plugin_entry, true);
291
292 logf("OP get_entry hash: %x lang id: %d db: %s", hash, lang_id, dat_file);
191 293
192 int fd = open(dat_file, O_RDONLY); 294 int fd = open(dat_file, O_RDONLY);
295 opret = op_find_entry(fd, entry, hash, lang_id);
296 close(fd);
193 297
194 if (fd >= 0) 298 if (opret < 0) /* nothing found */
195 { 299 {
196 while (read(fd, entry, op_entry_sz) == op_entry_sz) 300 op_clear_entry(entry);
197 {
198 record++;
199 if (hash == 0 || entry->hash == hash)
200 {
201 /* NULL terminate fields NOTE -- all are actually +1 larger */
202 entry->name[OPEN_PLUGIN_NAMESZ] = '\0';
203 /*entry->key[OPEN_PLUGIN_BUFSZ] = '\0';*/
204 entry->path[OPEN_PLUGIN_BUFSZ] = '\0';
205 entry->param[OPEN_PLUGIN_BUFSZ] = '\0';
206 ret = record;
207 break;
208 }
209 }
210 close(fd);
211 }
212 if (ret < 0)
213 {
214 memset(entry, 0, op_entry_sz);
215 entry->lang_id = -1;
216 } 301 }
217 } 302 }
218 303
219 return ret; 304 return opret;
305}
306
307#if 0 //unused
308static int open_plugin_langid_get_entry(int32_t lang_id,
309 struct open_plugin_entry_t *entry,
310 const char *dat_file)
311{
312 return op_get_entry(0, lang_id, entry, dat_file);
313}
314#endif
315
316static int open_plugin_hash_get_entry(uint32_t hash,
317 struct open_plugin_entry_t *entry,
318 const char *dat_file)
319{
320 return op_get_entry(hash, OPEN_PLUGIN_LANG_IGNORE, entry, dat_file);
220} 321}
221 322
222int open_plugin_get_entry(const char *key, struct open_plugin_entry_t *entry) 323int open_plugin_get_entry(const char *key, struct open_plugin_entry_t *entry)
223{ 324{
325 if (!key || !entry)
326 return OPEN_PLUGIN_NOT_FOUND;
327 int opret;
224 uint32_t hash; 328 uint32_t hash;
225 key = P2STR((unsigned char *)key); 329 int32_t lang_id = P2ID((unsigned char *)key);
330 const char* skey = P2STR((unsigned char *)key); /* string|LANGPTR => string */
331
332 open_plugin_get_hash(strip_rockbox_root(skey), &hash); /* in open_plugin.h */
333
334 opret = op_get_entry(hash, lang_id, entry, OPEN_PLUGIN_DAT);
335 logf("OP entry hash: %x lang id: %d ret: %d key: %s", hash, lang_id, opret, skey);
226 336
227 open_plugin_get_hash(key, &hash); /* in open_plugin.h */ 337 if (opret == OPEN_PLUGIN_NOT_FOUND && lang_id > OPEN_PLUGIN_LANG_INVALID)
228 return open_plugin_hash_get_entry(hash, entry, OPEN_PLUGIN_DAT); 338 { /* try rb defaults */
339 opret = op_get_entry(hash, lang_id, entry, OPEN_RBPLUGIN_DAT);
340 logf("OP rb_entry hash: %x lang id: %d ret: %d key: %s", hash, lang_id, opret, skey);
341 /* add to the user plugin.dat file if found */
342 op_update_dat(entry, false);
343
344 }
345 logf("OP entry ret: %s", (opret == OPEN_PLUGIN_NOT_FOUND ? "Not Found":"Found"));
346 return opret;
229} 347}
230 348
231int open_plugin_run(const char *key) 349int open_plugin_run(const char *key)
232{ 350{
233 int ret = 0; 351 int ret = 0;
234 const char *path; 352 int opret = open_plugin_get_entry(key, &open_plugin_entry);
235 const char *param; 353 if (opret == OPEN_PLUGIN_NEEDS_FLUSHED)
236
237 if (open_plugin_get_entry(key, &open_plugin_entry) == -2) /* entry needs flushed */
238 op_update_dat(&open_plugin_entry, false); 354 op_update_dat(&open_plugin_entry, false);
355 const char *path = open_plugin_entry.path;
356 const char *param = open_plugin_entry.param;
357
358 logf("OP run key: %s ret: %d name: %s",
359 (key ? P2STR((unsigned char *)key):"No Key"), opret, open_plugin_entry.name);
360 logf("OP run: %s %s %s", open_plugin_entry.name, path, param);
239 361
240 path = open_plugin_entry.path;
241 param = open_plugin_entry.param;
242 if (param[0] == '\0') 362 if (param[0] == '\0')
243 param = NULL; 363 param = NULL;
244 364
245 if (path) 365 ret = plugin_load(path, param);
246 ret = plugin_load(path, param);
247 366
248 if (ret != GO_TO_PLUGIN) 367 if (ret != GO_TO_PLUGIN)
249 op_clear_entry(&open_plugin_entry); 368 op_clear_entry(&open_plugin_entry);
@@ -253,6 +372,7 @@ int open_plugin_run(const char *key)
253 372
254void open_plugin_cache_flush(void) 373void open_plugin_cache_flush(void)
255{ 374{
375 logf("OP *cache flush*");
256 op_update_dat(&open_plugin_entry, true); 376 op_update_dat(&open_plugin_entry, true);
257} 377}
258 378
diff --git a/apps/open_plugin.h b/apps/open_plugin.h
index 8c09c4ac58..e1d49bf329 100644
--- a/apps/open_plugin.h
+++ b/apps/open_plugin.h
@@ -32,17 +32,28 @@
32#ifndef __PCTOOL__ 32#ifndef __PCTOOL__
33/* open_plugin path lookup */ 33/* open_plugin path lookup */
34#define OPEN_PLUGIN_DAT PLUGIN_DIR "/plugin.dat" 34#define OPEN_PLUGIN_DAT PLUGIN_DIR "/plugin.dat"
35#define OPEN_RBPLUGIN_DAT PLUGIN_DIR "/rb_plugins.dat"
35#define OPEN_PLUGIN_BUFSZ MAX_PATH 36#define OPEN_PLUGIN_BUFSZ MAX_PATH
36#define OPEN_PLUGIN_NAMESZ 32 37#define OPEN_PLUGIN_NAMESZ 32
38
39enum {
40 OPEN_PLUGIN_LANG_INVALID = (-1),
41 OPEN_PLUGIN_LANG_IGNORE = (-2),
42 OPEN_PLUGIN_LANG_IGNOREALL = (-3),
43 OPEN_PLUGIN_NOT_FOUND = (-1),
44 OPEN_PLUGIN_NEEDS_FLUSHED = (-2)
45};
46
37struct open_plugin_entry_t 47struct open_plugin_entry_t
38{ 48{
49/* hash and lang_id need to be the first items */
39 uint32_t hash; 50 uint32_t hash;
40 int32_t lang_id; 51 int32_t lang_id;
41 char name[OPEN_PLUGIN_NAMESZ+1]; 52 char name[OPEN_PLUGIN_NAMESZ+1];
42 /*char key[OPEN_PLUGIN_BUFSZ+1];*/ 53 /*char key[OPEN_PLUGIN_BUFSZ+1];*/
43 char path[OPEN_PLUGIN_BUFSZ+1]; 54 char path[OPEN_PLUGIN_BUFSZ+1];
44 char param[OPEN_PLUGIN_BUFSZ+1]; 55 char param[OPEN_PLUGIN_BUFSZ+1];
45}; 56}__attribute__((packed));
46 57
47inline static void open_plugin_get_hash(const char *key, uint32_t *hash) 58inline static void open_plugin_get_hash(const char *key, uint32_t *hash)
48{ 59{
diff --git a/apps/root_menu.c b/apps/root_menu.c
index 2eab43f504..a67bb41cde 100644
--- a/apps/root_menu.c
+++ b/apps/root_menu.c
@@ -848,7 +848,8 @@ void root_menu(void)
848 } 848 }
849 } 849 }
850 850
851 bool flush = (open_plugin_get_entry(key, &open_plugin_entry) == -2); 851 int opret = open_plugin_get_entry(key, &open_plugin_entry);
852 bool flush = (opret == OPEN_PLUGIN_NEEDS_FLUSHED);
852 char *path = open_plugin_entry.path; 853 char *path = open_plugin_entry.path;
853 char *param = open_plugin_entry.param; 854 char *param = open_plugin_entry.param;
854 if (param[0] == '\0') 855 if (param[0] == '\0')