1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
|
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2014 by Michael Sevakis
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#ifndef _DIRCACHE_REDIRECT_H_
#include "rbpaths.h"
#include "pathfuncs.h"
#include "dir.h"
#include "dircache.h"
#include "file.h"
#if defined(HAVE_MULTIBOOT) && !defined(SIMULATOR) && !defined(BOOTLOADER)
#include "rb-loader.h"
#include "multiboot.h"
#include "bootdata.h"
#endif
#ifndef RB_ROOT_VOL_HIDDEN
#define RB_ROOT_VOL_HIDDEN(v) (0 == 0)
#endif
#ifndef RB_ROOT_CONTENTS_DIR
#define RB_ROOT_CONTENTS_DIR "/"
#endif
/***
** Internal redirects that depend upon whether or not dircache is made
**
** Some stuff deals with it, some doesn't right now. This is a nexus point..
**/
/** File binding **/
static inline void get_rootinfo_internal(struct file_base_info *infop)
{
#ifdef HAVE_DIRCACHE
dircache_get_rootinfo(infop);
#else
(void)infop;
#endif
}
static inline void fileobj_bind_file(struct file_base_binding *bindp)
{
#ifdef HAVE_DIRCACHE
dircache_bind_file(bindp);
#else
file_binding_insert_last(bindp);
#endif
}
static inline void fileobj_unbind_file(struct file_base_binding *bindp)
{
#ifdef HAVE_DIRCACHE
dircache_unbind_file(bindp);
#else
file_binding_remove(bindp);
#endif
}
/** File event handlers **/
static inline void fileop_onopen_internal(struct filestr_base *stream,
struct file_base_info *srcinfop,
unsigned int callflags)
{
fileobj_fileop_open(stream, srcinfop, callflags);
}
static inline void fileop_onclose_internal(struct filestr_base *stream)
{
fileobj_fileop_close(stream);
}
static inline void fileop_oncreate_internal(struct filestr_base *stream,
struct file_base_info *srcinfop,
unsigned int callflags,
struct file_base_info *dirinfop,
const char *basename)
{
#ifdef HAVE_DIRCACHE
dircache_dcfile_init(&srcinfop->dcfile);
#endif
fileobj_fileop_create(stream, srcinfop, callflags);
#ifdef HAVE_DIRCACHE
struct dirinfo_native din;
fill_dirinfo_native(&din);
dircache_fileop_create(dirinfop, stream->bindp, basename, &din);
#endif
(void)dirinfop; (void)basename;
}
static inline void fileop_onremove_internal(struct filestr_base *stream,
struct file_base_info *oldinfop)
{
fileobj_fileop_remove(stream, oldinfop);
#ifdef HAVE_DIRCACHE
dircache_fileop_remove(stream->bindp);
#endif
}
static inline void fileop_onrename_internal(struct filestr_base *stream,
struct file_base_info *oldinfop,
struct file_base_info *dirinfop,
const char *basename)
{
fileobj_fileop_rename(stream, oldinfop);
#ifdef HAVE_DIRCACHE
dircache_fileop_rename(dirinfop, stream->bindp, basename);
#endif
(void)dirinfop; (void)basename;
}
static inline void fileop_onsync_internal(struct filestr_base *stream)
{
fileobj_fileop_sync(stream);
#ifdef HAVE_DIRCACHE
struct dirinfo_native din;
fill_dirinfo_native(&din);
dircache_fileop_sync(stream->bindp, &din);
#endif
}
#if defined(HAVE_MULTIBOOT) && !defined(SIMULATOR) && !defined(BOOTLOADER)
static inline bool multiboot_is_boot_volume(int volume)
{
if (boot_data.version == 0)
{
/*
* Version 0 bootloaders just pass the volume number, but that's
* dynamically assigned and sometimes differs by the time we get
* into the firmware. So we can't rely on the volume passed by
* the bootloader.
*/
#if CONFIG_CPU == X1000
/* The affected X1000 players only have one drive to begin with */
return volume_drive(volume) == 0;
#else
/* FIXME: Anything else that can get here is a Sansa. */
return volume_drive(volume) == boot_data._boot_volume ||
volume == boot_data._boot_volume;
#endif
}
if (boot_data.version == 1)
{
/*
* Since version 1 the bootloader passes drive and partition
* number which unambiguously identifies the boot volume.
*/
return volume_drive(volume) == boot_data.boot_drive &&
volume_partition(volume) == boot_data.boot_partition;
}
return false;
}
#endif
static inline void volume_onmount_internal(IF_MV_NONVOID(int volume))
{
#if defined(HAVE_MULTIBOOT) && !defined(SIMULATOR) && !defined(BOOTLOADER)
char path[VOL_MAX_LEN+2];
char rtpath[MAX_PATH / 2];
make_volume_root(volume, path);
if (boot_data_valid)
{
/* we need to mount the drive before we can access it */
root_mount_path(path, 0); /* root could be different folder don't hide */
if (multiboot_is_boot_volume(IF_MV_VOL(volume)))
{
/* get the full path to the BOOTFILE
ie. /<0>/redirectdir/.rockbox/rockbox.ext */
int rtlen = get_redirect_dir(rtpath, sizeof(rtpath),
volume, BOOTDIR, BOOTFILE);
if (rtlen <= 0 || rtlen >= (int) sizeof(rtpath))
rtlen = 0; /* path too long or sprintf error */
else if (file_exists(rtpath))
{
rtlen = get_redirect_dir(rtpath, sizeof(rtpath), volume, "", "");
while (rtlen > 0 && rtpath[--rtlen] == PATH_SEPCH)
rtpath[rtlen] = '\0'; /* remove separators */
}
else
rtlen = 0; /* No BOOTFILE found */
#if 0 /*removed, causes issues with playback for now?*/
if (rtlen <= 0 || rtpath[rtlen] == VOL_END_TOK)
root_unmount_volume(volume); /* unmount so root can be hidden*/
#endif
if (rtlen <= 0 || root_mount_path(rtpath, NSITEM_CONTENTS) != 0)
{ /* Error occurred, card removed? Set root to default */
boot_data_valid = false;
root_unmount_volume(volume); /* unmount so root can be hidden*/
goto standard_redirect;
}
}
}
else
{
standard_redirect:
root_mount_path(path, RB_ROOT_VOL_HIDDEN(volume) ? NSITEM_HIDDEN : 0);
if (volume == path_strip_volume(RB_ROOT_CONTENTS_DIR, NULL, false))
root_mount_path(RB_ROOT_CONTENTS_DIR, NSITEM_CONTENTS);
}
#elif defined(HAVE_MULTIVOLUME)
char path[VOL_MAX_LEN+2];
make_volume_root(volume, path);
root_mount_path(path, RB_ROOT_VOL_HIDDEN(volume) ? NSITEM_HIDDEN : 0);
if (volume == path_strip_volume(RB_ROOT_CONTENTS_DIR, NULL, false))
root_mount_path(RB_ROOT_CONTENTS_DIR, NSITEM_CONTENTS);
#else
const char *path = PATH_ROOTSTR;
root_mount_path(path, RB_ROOT_VOL_HIDDEN(volume) ? NSITEM_HIDDEN : 0);
root_mount_path(RB_ROOT_CONTENTS_DIR, NSITEM_CONTENTS);
#endif /* HAVE_MULTIBOOT */
#ifdef HAVE_DIRCACHE
dircache_mount();
#endif
}
static inline void volume_onunmount_internal(IF_MV_NONVOID(int volume))
{
#ifdef HAVE_DIRCACHE
/* First, to avoid update of something about to be destroyed anyway */
dircache_unmount(IF_MV(volume));
#endif
root_unmount_volume(IF_MV(volume));
fileobj_mgr_unmount(IF_MV(volume));
}
static inline void fileop_onunmount_internal(struct filestr_base *stream)
{
if (stream->flags & FD_WRITE)
force_close_writer_internal(stream); /* try to save stuff */
else
fileop_onclose_internal(stream); /* just readers, bye */
}
/** Directory reading **/
static inline int readdir_dirent(struct filestr_base *stream,
struct dirscan_info *scanp,
struct DIRENT *entry)
{
#ifdef HAVE_DIRCACHE
return dircache_readdir_dirent(stream, scanp, entry);
#else
return uncached_readdir_dirent(stream, scanp, entry);
#endif
}
static inline void rewinddir_dirent(struct dirscan_info *scanp)
{
#ifdef HAVE_DIRCACHE
dircache_rewinddir_dirent(scanp);
#else
uncached_rewinddir_dirent(scanp);
#endif
}
static inline int readdir_internal(struct filestr_base *stream,
struct file_base_info *infop,
struct fat_direntry *fatent)
{
#ifdef HAVE_DIRCACHE
return dircache_readdir_internal(stream, infop, fatent);
#else
return uncached_readdir_internal(stream, infop, fatent);
#endif
}
static inline void rewinddir_internal(struct file_base_info *infop)
{
#ifdef HAVE_DIRCACHE
dircache_rewinddir_internal(infop);
#else
uncached_rewinddir_internal(infop);
#endif
}
/** Misc. stuff **/
static inline struct fat_direntry *get_dir_fatent_dircache(void)
{
#ifdef HAVE_DIRCACHE
return get_dir_fatent();
#else
return NULL;
#endif
}
#endif /* _DIRCACHE_REDIRECT_H_ */
|