summaryrefslogtreecommitdiff
path: root/firmware/include
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2013-08-05 22:02:45 -0400
committerMichael Sevakis <jethead71@rockbox.org>2014-08-30 03:48:23 +0200
commit7d1a47cf13726c95ac46027156cc12dd9da5b855 (patch)
treeeb20d07656806479a8e1fea25887a490ea30d1d8 /firmware/include
parent95a4c3afcd53a1f8b835dec33de51f9c304de4d9 (diff)
downloadrockbox-7d1a47cf13726c95ac46027156cc12dd9da5b855.tar.gz
rockbox-7d1a47cf13726c95ac46027156cc12dd9da5b855.zip
Rewrite filesystem code (WIP)
This patch redoes the filesystem code from the FAT driver up to the clipboard code in onplay.c. Not every aspect of this is finished therefore it is still "WIP". I don't wish to do too much at once (haha!). What is left to do is get dircache back in the sim and find an implementation for the dircache indicies in the tagcache and playlist code or do something else that has the same benefit. Leaving these out for now does not make anything unusable. All the basics are done. Phone app code should probably get vetted (and app path handling just plain rewritten as environment expansions); the SDL app and Android run well. Main things addressed: 1) Thread safety: There is none right now in the trunk code. Most of what currently works is luck when multiple threads are involved or multiple descriptors to the same file are open. 2) POSIX compliance: Many of the functions behave nothing like their counterparts on a host system. This leads to inconsistent code or very different behavior from native to hosted. One huge offender was rename(). Going point by point would fill a book. 3) Actual running RAM usage: Many targets will use less RAM and less stack space (some more RAM because I upped the number of cache buffers for large memory). There's very little memory lying fallow in rarely-used areas (see 'Key core changes' below). Also, all targets may open the same number of directory streams whereas before those with less than 8MB RAM were limited to 8, not 12 implying those targets will save slightly less. 4) Performance: The test_disk plugin shows markedly improved performance, particularly in the area of (uncached) directory scanning, due partly to more optimal directory reading and to a better sector cache algorithm. Uncached times tend to be better while there is a bit of a slowdown in dircache due to it being a bit heavier of an implementation. It's not noticeable by a human as far as I can say. Key core changes: 1) Files and directories share core code and data structures. 2) The filesystem code knows which descriptors refer to same file. This ensures that changes from one stream are appropriately reflected in every open descriptor for that file (fileobj_mgr.c). 3) File and directory cache buffers are borrowed from the main sector cache. This means that when they are not in use by a file, they are not wasted, but used for the cache. Most of the time, only a few of them are needed. It also means that adding more file and directory handles is less expensive. All one must do in ensure a large enough cache to borrow from. 4) Relative path components are supported and the namespace is unified. It does not support full relative paths to an implied current directory; what is does support is use of "." and "..". Adding the former would not be very difficult. The namespace is unified in the sense that volumes may be specified several times along with relative parts, e.g.: "/<0>/foo/../../<1>/bar" :<=> "/<1>/bar". 5) Stack usage is down due to sharing of data, static allocation and less duplication of strings on the stack. This requires more serialization than I would like but since the number of threads is limited to a low number, the tradoff in favor of the stack seems reasonable. 6) Separates and heirarchicalizes (sic) the SIM and APP filesystem code. SIM path and volume handling is just like the target. Some aspects of the APP file code get more straightforward (e.g. no path hashing is needed). Dircache: Deserves its own section. Dircache is new but pays homage to the old. The old one was not compatible and so it, since it got redone, does all the stuff it always should have done such as: 1) It may be update and used at any time during the build process. No longer has one to wait for it to finish building to do basic file management (create, remove, rename, etc.). 2) It does not need to be either fully scanned or completely disabled; it can be incomplete (i.e. overfilled, missing paths), still be of benefit and be correct. 3) Handles mounting and dismounting of individual volumes which means a full rebuild is not needed just because you pop a new SD card in the slot. Now, because it reuses its freed entry data, may rebuild only that volume. 4) Much more fundamental to the file code. When it is built, it is the keeper of the master file list whether enabled or not ("disabled" is just a state of the cache). Its must always to ready to be started and bind all streams opened prior to being enabled. 5) Maintains any short filenames in OEM format which means that it does not need to be rebuilt when changing the default codepage. Miscellaneous Compatibility: 1) Update any other code that would otherwise not work such as the hotswap mounting code in various card drivers. 2) File management: Clipboard needed updating because of the behavioral changes. Still needs a little more work on some finer points. 3) Remove now-obsolete functionality such as the mutex's "no preempt" flag (which was only for the prior FAT driver). 4) struct dirinfo uses time_t rather than raw FAT directory entry time fields. I plan to follow up on genericizing everything there (i.e. no FAT attributes). 5) unicode.c needed some redoing so that the file code does not try try to load codepages during a scan, which is actually a problem with the current code. The default codepage, if any is required, is now kept in RAM separarately (bufalloced) from codepages specified to iso_decode() (which must not be bufalloced because the conversion may be done by playback threads). Brings with it some additional reusable core code: 1) Revised file functions: Reusable code that does things such as safe path concatenation and parsing without buffer limitations or data duplication. Variants that copy or alter the input path may be based off these. To do: 1) Put dircache functionality back in the sim. Treating it internally as a different kind of file system seems the best approach at this time. 2) Restore use of dircache indexes in the playlist and database or something effectively the same. Since the cache doesn't have to be complete in order to be used, not getting a hit on the cache doesn't unambiguously say if the path exists or not. Change-Id: Ia30f3082a136253e3a0eae0784e3091d138915c8 Reviewed-on: http://gerrit.rockbox.org/566 Reviewed-by: Michael Sevakis <jethead71@rockbox.org> Tested: Michael Sevakis <jethead71@rockbox.org>
Diffstat (limited to 'firmware/include')
-rw-r--r--firmware/include/dir.h91
-rw-r--r--firmware/include/dir_uncached.h107
-rw-r--r--firmware/include/dircache.h209
-rw-r--r--firmware/include/dircache_redirect.h198
-rw-r--r--firmware/include/disk_cache.h83
-rw-r--r--firmware/include/file.h125
-rw-r--r--firmware/include/file_internal.h371
-rw-r--r--firmware/include/fileobj_mgr.h56
-rw-r--r--firmware/include/filesystem-native.h107
-rw-r--r--firmware/include/fs_attr.h39
-rw-r--r--firmware/include/rb-loader.h1
-rw-r--r--firmware/include/rbunicode.h18
12 files changed, 1133 insertions, 272 deletions
diff --git a/firmware/include/dir.h b/firmware/include/dir.h
index 6e8b70588e..f7719823a9 100644
--- a/firmware/include/dir.h
+++ b/firmware/include/dir.h
@@ -18,46 +18,71 @@
18 * KIND, either express or implied. 18 * KIND, either express or implied.
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21
22#ifndef _DIR_H_ 21#ifndef _DIR_H_
23#define _DIR_H_ 22#define _DIR_H_
24 23
24#include <sys/types.h>
25#include <fcntl.h>
26#include <time.h>
25#include "config.h" 27#include "config.h"
28#include "fs_attr.h"
26 29
27#define ATTR_READ_ONLY 0x01 30#if defined (APPLICATION)
28#define ATTR_HIDDEN 0x02 31#include "filesystem-app.h"
29#define ATTR_SYSTEM 0x04 32#elif defined(SIMULATOR) || defined(__PCTOOL__)
30#define ATTR_VOLUME_ID 0x08 33#include "../../uisimulator/common/filesystem-sim.h"
31#define ATTR_DIRECTORY 0x10
32#define ATTR_ARCHIVE 0x20
33#define ATTR_VOLUME 0x40 /* this is a volume, not a real directory */
34#define ATTR_LINK 0x80
35
36#ifdef HAVE_DIRCACHE
37# include "dircache.h"
38# define DIR DIR_CACHED
39# define dirent dirent_cached
40# define opendir opendir_cached
41# define closedir closedir_cached
42# define readdir readdir_cached
43# define closedir closedir_cached
44# define mkdir mkdir_cached
45# define rmdir rmdir_cached
46#else 34#else
47# include "dir_uncached.h" 35#include "filesystem-native.h"
48# define DIR DIR_UNCACHED 36#endif
49# define dirent dirent_uncached 37
50# define opendir opendir_uncached 38#ifndef DIRFUNCTIONS_DEFINED
51# define closedir closedir_uncached 39#ifndef opendir
52# define readdir readdir_uncached 40#define opendir FS_PREFIX(opendir)
53# define closedir closedir_uncached 41#endif
54# define mkdir mkdir_uncached 42#ifndef readdir
55# define rmdir rmdir_uncached 43#define readdir FS_PREFIX(readdir)
44#endif
45#ifndef readdir_r
46#define readdir_r FS_PREFIX(readdir_r)
47#endif
48#ifndef rewinddir
49#define rewinddir FS_PREFIX(rewinddir)
56#endif 50#endif
51#ifndef closedir
52#define closedir FS_PREFIX(closedir)
53#endif
54#ifndef mkdir
55#define mkdir FS_PREFIX(mkdir)
56#endif
57#ifndef rmdir
58#define rmdir FS_PREFIX(rmdir)
59#endif
60#ifndef samedir
61#define samedir FS_PREFIX(samedir)
62#endif
63#ifndef dir_exists
64#define dir_exists FS_PREFIX(dir_exists)
65#endif
66#endif /* !DIRFUNCTIONS_DEFINED */
57 67
68#ifndef DIRENT_DEFINED
69struct DIRENT
70{
71 struct dirinfo_native info; /* platform extra info */
72 char d_name[MAX_PATH]; /* UTF-8 name of entry (last!) */
73};
74#endif /* DIRENT_DEFINED */
58 75
59typedef DIR* (*opendir_func)(const char* name); 76struct dirinfo
60typedef int (*closedir_func)(DIR* dir); 77{
61typedef struct dirent* (*readdir_func)(DIR* dir); 78 unsigned int attribute; /* attribute bits of file */
79 off_t size; /* binary size of file */
80 time_t mtime; /* local file time */
81};
62 82
63#endif 83#ifndef DIRFUNCTIONS_DECLARED
84/* TIP: set errno to zero before calling to see if anything failed */
85struct dirinfo dir_get_info(DIR *dirp, struct DIRENT *entry);
86#endif /* !DIRFUNCTIONS_DECLARED */
87
88#endif /* _DIR_H_ */
diff --git a/firmware/include/dir_uncached.h b/firmware/include/dir_uncached.h
deleted file mode 100644
index 6443d5ba97..0000000000
--- a/firmware/include/dir_uncached.h
+++ /dev/null
@@ -1,107 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: dir.h 13741 2007-06-30 02:08:27Z jethead71 $
9 *
10 * Copyright (C) 2002 by Björn Stenberg
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef _DIR_UNCACHED_H_
22#define _DIR_UNCACHED_H_
23
24#include "config.h"
25
26struct dirinfo {
27 int attribute;
28 long size;
29 unsigned short wrtdate;
30 unsigned short wrttime;
31};
32
33#include <stdbool.h>
34#include "file.h"
35
36#if defined(SIMULATOR) || defined(__PCTOOL__)
37# define dirent_uncached sim_dirent
38# define DIR_UNCACHED SIM_DIR
39# define opendir_uncached sim_opendir
40# define readdir_uncached sim_readdir
41# define closedir_uncached sim_closedir
42# define mkdir_uncached sim_mkdir
43# define rmdir_uncached sim_rmdir
44#elif defined(APPLICATION)
45# include "rbpaths.h"
46# define DIRENT_DEFINED
47# define DIR_DEFINED
48# define dirent_uncached dirent
49# define DIR_UNCACHED DIR
50# define opendir_uncached app_opendir
51# define readdir_uncached app_readdir
52# define closedir_uncached app_closedir
53# define mkdir_uncached app_mkdir
54# define rmdir_uncached app_rmdir
55#endif
56
57
58#ifndef DIRENT_DEFINED
59struct dirent_uncached {
60 unsigned char d_name[MAX_PATH];
61 struct dirinfo info;
62 long startcluster;
63};
64#endif
65
66#include "fat.h"
67
68#ifndef DIR_DEFINED
69typedef struct {
70#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
71 struct fat_dir fatdir CACHEALIGN_ATTR;
72 bool busy;
73 long startcluster;
74 struct dirent_uncached theent;
75#ifdef HAVE_MULTIVOLUME
76 int volumecounter; /* running counter for faked volume entries */
77#endif
78#else
79 /* simulator/application: */
80 void *dir; /* actually a DIR* dir */
81 char *name;
82#endif
83} DIR_UNCACHED CACHEALIGN_ATTR;
84#endif
85
86#ifdef HAVE_HOTSWAP
87char *get_volume_name(int volume);
88#endif
89
90#ifdef HAVE_MULTIVOLUME
91 int strip_volume(const char*, char*);
92#endif
93
94#ifndef DIRFUNCTIONS_DEFINED
95
96extern DIR_UNCACHED* opendir_uncached(const char* name);
97extern int closedir_uncached(DIR_UNCACHED* dir);
98extern int mkdir_uncached(const char* name);
99extern int rmdir_uncached(const char* name);
100
101extern struct dirent_uncached* readdir_uncached(DIR_UNCACHED* dir);
102
103extern int release_dirs(int volume);
104
105#endif /* DIRFUNCTIONS_DEFINED */
106
107#endif
diff --git a/firmware/include/dircache.h b/firmware/include/dircache.h
index 019ccf49b7..7e8c764e7f 100644
--- a/firmware/include/dircache.h
+++ b/firmware/include/dircache.h
@@ -8,6 +8,7 @@
8 * $Id$ 8 * $Id$
9 * 9 *
10 * Copyright (C) 2005 by Miika Pekkarinen 10 * Copyright (C) 2005 by Miika Pekkarinen
11 * Copyright (C) 2014 by Michael Sevakis
11 * 12 *
12 * This program is free software; you can redistribute it and/or 13 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License 14 * modify it under the terms of the GNU General Public License
@@ -21,84 +22,154 @@
21#ifndef _DIRCACHE_H 22#ifndef _DIRCACHE_H
22#define _DIRCACHE_H 23#define _DIRCACHE_H
23 24
24#include "config.h" 25#include "mv.h"
25#include "dir_uncached.h" 26#include <string.h> /* size_t */
26#include <string.h> /* size_t */ 27#include <sys/types.h> /* ssize_t */
27 28
28#ifdef HAVE_DIRCACHE 29#ifdef HAVE_DIRCACHE
29 30
30#define DIRCACHE_RESERVE (1024*64) 31/****************************************************************************
31#define DIRCACHE_LIMIT (1024*1024*6) 32 ** Configurable values
32 33 **/
33#define DIRCACHE_APPFLAG_TAGCACHE 0x0001 34
34#define DIRCACHE_APPFLAG_PLAYLIST 0x0002 35#if 0
35 36/* enable dumping code */
36/* Internal structures. */ 37#define DIRCACHE_DUMPSTER
37struct travel_data { 38#define DIRCACHE_DUMPSTER_BIN "/dircache_dump.bin"
38 struct dircache_entry *first; 39#define DIRCACHE_DUMPSTER_CSV "/dircache_dump.csv"
39 struct dircache_entry *ce;
40 struct dircache_entry *down_entry;
41#if (CONFIG_PLATFORM & PLATFORM_HOSTED)
42 DIR_UNCACHED *dir, *newdir;
43 struct dirent_uncached *entry;
44#else
45 struct fat_dir *dir;
46 struct fat_dir newdir;
47 struct fat_direntry entry;
48#endif 40#endif
49 int pathpos; 41
42/* dircache builds won't search below this but will work down to this point
43 while below it the cache will just pass requests through to the storage;
44 the limiting factor is the scanning thread stack size, not the
45 implementation -- tune the two together */
46#define DIRCACHE_MAX_DEPTH 15
47#define DIRCACHE_STACK_SIZE (DEFAULT_STACK_SIZE + 0x100)
48
49/* memory buffer constants that control allocation */
50#define DIRCACHE_RESERVE (1024*64) /* 64 KB - new entry slack */
51#define DIRCACHE_MIN (1024*1024*1) /* 1 MB - provision min size */
52#define DIRCACHE_LIMIT (1024*1024*6) /* 6 MB - provision max size */
53
54/* make it easy to change serialnumber size without modifying anything else;
55 32 bits allows 21845 builds before wrapping in a 6MB cache that is filled
56 exclusively with entries and nothing else (32 byte entries), making that
57 figure pessimistic */
58typedef uint32_t dc_serial_t;
59
60/**
61 ****************************************************************************/
62
63#if CONFIG_PLATFORM & PLATFORM_NATIVE
64/* native dircache is lower-level than on a hosted target */
65#define DIRCACHE_NATIVE
66#endif
67
68struct dircache_file
69{
70 int idx; /* this file's cache index */
71 dc_serial_t serialnum; /* this file's serial number */
50}; 72};
51 73
52struct dirent_cached { 74enum dircache_status
53 struct dirinfo info; 75{
54 char *d_name; 76 DIRCACHE_IDLE = 0, /* no volume is initialized */
55 long startcluster; 77 DIRCACHE_SCANNING = 1, /* dircache is scanning a volume */
78 DIRCACHE_READY = 2, /* dircache is ready to be used */
79};
80
81/** Dircache control **/
82void dircache_wait(void);
83void dircache_suspend(void);
84int dircache_resume(void);
85int dircache_enable(void);
86void dircache_disable(void);
87void dircache_free_buffer(void);
88
89/** Volume mounting **/
90void dircache_mount(void); /* always tries building everything it can */
91void dircache_unmount(IF_MV_NONVOID(int volume));
92
93
94/** File API service functions **/
95
96/* avoid forcing #include of file_internal.h, fat.h and dir.h */
97struct filestr_base;
98struct file_base_info;
99struct file_base_binding;
100struct dirent;
101struct dirscan_info;
102struct dirinfo_native;
103
104int dircache_readdir_dirent(struct filestr_base *stream,
105 struct dirscan_info *scanp,
106 struct dirent *entry);
107void dircache_rewinddir_dirent(struct dirscan_info *scanp);
108
109#ifdef DIRCACHE_NATIVE
110struct fat_direntry;
111int dircache_readdir_internal(struct filestr_base *stream,
112 struct file_base_info *infop,
113 struct fat_direntry *fatent);
114void dircache_rewinddir_internal(struct file_base_info *info);
115#endif /* DIRCACHE_NATIVE */
116
117
118/** Dircache live updating **/
119
120void dircache_get_rootinfo(struct file_base_info *infop);
121void dircache_bind_file(struct file_base_binding *bindp);
122void dircache_unbind_file(struct file_base_binding *bindp);
123void dircache_fileop_create(struct file_base_info *dirinfop,
124 struct file_base_binding *bindp,
125 const char *basename,
126 const struct dirinfo_native *dinp);
127void dircache_fileop_rename(struct file_base_info *dirinfop,
128 struct file_base_binding *bindp,
129 const char *basename);
130void dircache_fileop_remove(struct file_base_binding *bindp);
131void dircache_fileop_sync(struct file_base_binding *infop,
132 const struct dirinfo_native *dinp);
133
134
135/** Dircache paths and files **/
136ssize_t dircache_get_path(const struct dircache_file *dcfilep, char *buf,
137 size_t size);
138int dircache_get_file(const char *path, struct dircache_file *dcfilep);
139
140
141/** Debug screen/info stuff **/
142
143struct dircache_info
144{
145 enum dircache_status status; /* current composite status value */
146 const char *statusdesc; /* pointer to string describing 'status' */
147 size_t last_size; /* cache size after last build */
148 size_t size; /* total size of entries (with holes) */
149 size_t sizeused; /* bytes of 'size' actually utilized */
150 size_t size_limit; /* maximum possible size */
151 size_t reserve; /* size of reserve area */
152 size_t reserve_used; /* amount of reserve used */
153 unsigned int entry_count; /* number of cache entries */
154 long build_ticks; /* total time used to build cache */
56}; 155};
57 156
58typedef struct { 157void dircache_get_info(struct dircache_info *info);
59 bool busy; 158#ifdef DIRCACHE_DUMPSTER
60 struct dirent_cached theent; /* .attribute is set to -1 on init(opendir) */ 159void dircache_dump(void);
61 int internal_entry; /* the current entry in the directory */ 160#endif /* DIRCACHE_DUMPSTER */
62 DIR_UNCACHED *regulardir; 161
63} DIR_CACHED;
64 162
65void dircache_init(void) INIT_ATTR; 163/** Misc. stuff **/
164void dircache_dcfile_init(struct dircache_file *dcfilep);
165
166#ifdef HAVE_EEPROM_SETTINGS
66int dircache_load(void); 167int dircache_load(void);
67int dircache_save(void); 168int dircache_save(void);
68int dircache_build(int last_size); 169#endif /* HAVE_EEPROM_SETTINGS */
69void* dircache_steal_buffer(size_t *size);
70bool dircache_is_enabled(void);
71bool dircache_is_initializing(void);
72void dircache_set_appflag(long mask);
73bool dircache_get_appflag(long mask);
74int dircache_get_entry_count(void);
75int dircache_get_cache_size(void);
76int dircache_get_reserve_used(void);
77int dircache_get_build_ticks(void);
78void dircache_disable(void);
79void dircache_suspend(void);
80bool dircache_resume(void);
81int dircache_get_entry_id(const char *filename);
82size_t dircache_copy_path(int index, char *buf, size_t size);
83
84/* the next two are internal for file.c */
85long _dircache_get_entry_startcluster(int id);
86struct dirinfo* _dircache_get_entry_dirinfo(int id);
87
88void dircache_bind(int fd, const char *path);
89void dircache_update_filesize(int fd, long newsize, long startcluster);
90void dircache_update_filetime(int fd);
91void dircache_mkdir(const char *path);
92void dircache_rmdir(const char *path);
93void dircache_remove(const char *name);
94void dircache_rename(const char *oldpath, const char *newpath);
95void dircache_add_file(const char *path, long startcluster);
96
97DIR_CACHED* opendir_cached(const char* name);
98struct dirent_cached* readdir_cached(DIR_CACHED* dir);
99int closedir_cached(DIR_CACHED *dir);
100int mkdir_cached(const char *name);
101int rmdir_cached(const char* name);
102#endif /* !HAVE_DIRCACHE */
103 170
104#endif 171void dircache_init(size_t last_size) INIT_ATTR;
172
173#endif /* HAVE_DIRCACHE */
174
175#endif /* _DIRCACHE_H */
diff --git a/firmware/include/dircache_redirect.h b/firmware/include/dircache_redirect.h
new file mode 100644
index 0000000000..15fb4bc38d
--- /dev/null
+++ b/firmware/include/dircache_redirect.h
@@ -0,0 +1,198 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2014 by Michael Sevakis
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef _DIRCACHE_REDIRECT_H_
22
23#include "dir.h"
24
25/***
26 ** Internal redirects that depend upon whether or not dircache is made
27 **/
28
29/** File binding **/
30
31static inline void get_rootinfo_internal(struct file_base_info *infop)
32{
33#ifdef HAVE_DIRCACHE
34 dircache_get_rootinfo(infop);
35#else
36 (void)infop;
37#endif
38}
39
40static inline void fileobj_bind_file(struct file_base_binding *bindp)
41{
42#ifdef HAVE_DIRCACHE
43 dircache_bind_file(bindp);
44#else
45 file_binding_insert_last(bindp);
46#endif
47}
48
49static inline void fileobj_unbind_file(struct file_base_binding *bindp)
50{
51#ifdef HAVE_DIRCACHE
52 dircache_unbind_file(bindp);
53#else
54 file_binding_remove(bindp);
55#endif
56}
57
58
59/** File event handlers **/
60
61static inline void fileop_onopen_internal(struct filestr_base *stream,
62 struct file_base_info *srcinfop,
63 unsigned int callflags)
64{
65 fileobj_fileop_open(stream, srcinfop, callflags);
66}
67
68static inline void fileop_onclose_internal(struct filestr_base *stream)
69{
70 fileobj_fileop_close(stream);
71}
72
73static inline void fileop_oncreate_internal(struct filestr_base *stream,
74 struct file_base_info *srcinfop,
75 unsigned int callflags,
76 struct file_base_info *dirinfop,
77 const char *basename)
78{
79#ifdef HAVE_DIRCACHE
80 dircache_dcfile_init(&srcinfop->dcfile);
81#endif
82 fileobj_fileop_create(stream, srcinfop, callflags);
83#ifdef HAVE_DIRCACHE
84 struct dirinfo_native din;
85 fill_dirinfo_native(&din);
86 dircache_fileop_create(dirinfop, stream->bindp, basename, &din);
87#endif
88 (void)dirinfop; (void)basename;
89}
90
91static inline void fileop_onremove_internal(struct filestr_base *stream,
92 struct file_base_info *oldinfop)
93{
94 fileobj_fileop_remove(stream, oldinfop);
95#ifdef HAVE_DIRCACHE
96 dircache_fileop_remove(stream->bindp);
97#endif
98}
99
100static inline void fileop_onrename_internal(struct filestr_base *stream,
101 struct file_base_info *oldinfop,
102 struct file_base_info *dirinfop,
103 const char *basename)
104{
105 fileobj_fileop_rename(stream, oldinfop);
106#ifdef HAVE_DIRCACHE
107 dircache_fileop_rename(dirinfop, stream->bindp, basename);
108#endif
109 (void)dirinfop; (void)basename;
110}
111
112static inline void fileop_onsync_internal(struct filestr_base *stream)
113{
114 fileobj_fileop_sync(stream);
115#ifdef HAVE_DIRCACHE
116 struct dirinfo_native din;
117 fill_dirinfo_native(&din);
118 dircache_fileop_sync(stream->bindp, &din);
119#endif
120}
121
122static inline void fileop_ontruncate_internal(struct filestr_base *stream)
123{
124 fileobj_fileop_truncate(stream);
125}
126
127static inline void volume_onmount_internal(IF_MV_NONVOID(int volume))
128{
129#ifdef HAVE_DIRCACHE
130 dircache_mount();
131#endif
132 IF_MV( (void)volume; )
133}
134
135static inline void volume_onunmount_internal(IF_MV_NONVOID(int volume))
136{
137 fileobj_mgr_unmount(IF_MV(volume));
138#ifdef HAVE_DIRCACHE
139 dircache_unmount(IF_MV(volume));
140#endif
141}
142
143
144/** Directory reading **/
145
146static inline int readdir_dirent(struct filestr_base *stream,
147 struct dirscan_info *scanp,
148 struct dirent *entry)
149{
150#ifdef HAVE_DIRCACHE
151 return dircache_readdir_dirent(stream, scanp, entry);
152#else
153 return uncached_readdir_dirent(stream, scanp, entry);
154#endif
155}
156
157static inline void rewinddir_dirent(struct dirscan_info *scanp)
158{
159#ifdef HAVE_DIRCACHE
160 dircache_rewinddir_dirent(scanp);
161#else
162 uncached_rewinddir_dirent(scanp);
163#endif
164}
165
166static inline int readdir_internal(struct filestr_base *stream,
167 struct file_base_info *infop,
168 struct fat_direntry *fatent)
169{
170#ifdef HAVE_DIRCACHE
171 return dircache_readdir_internal(stream, infop, fatent);
172#else
173 return uncached_readdir_internal(stream, infop, fatent);
174#endif
175}
176
177static inline void rewinddir_internal(struct file_base_info *infop)
178{
179#ifdef HAVE_DIRCACHE
180 dircache_rewinddir_internal(infop);
181#else
182 uncached_rewinddir_internal(infop);
183#endif
184}
185
186
187/** Misc. stuff **/
188
189static inline struct fat_direntry *get_dir_fatent_dircache(void)
190{
191#ifdef HAVE_DIRCACHE
192 return get_dir_fatent();
193#else
194 return NULL;
195#endif
196}
197
198#endif /* _DIRCACHE_REDIRECT_H_ */
diff --git a/firmware/include/disk_cache.h b/firmware/include/disk_cache.h
new file mode 100644
index 0000000000..725b3778cc
--- /dev/null
+++ b/firmware/include/disk_cache.h
@@ -0,0 +1,83 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2014 by Michael Sevakis
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef DISK_CACHE_H
22#define DISK_CACHE_H
23
24/* This needs enough for all file handles to have a buffer in the worst case
25 * plus at least one reserved exclusively for the cache client and a couple
26 * for other file system code. The buffers are put to use by the cache if not
27 * taken for another purpose (meaning nothing is wasted sitting fallow).
28 *
29 * One map per volume is maintained in order to avoid collisions between
30 * volumes that would slow cache probing. DC_MAP_NUM_ENTRIES is the number
31 * for each map per volume. The buffers themselves are shared.
32 */
33#if MEMORYSIZE < 8
34#define DC_NUM_ENTRIES 32
35#define DC_MAP_NUM_ENTRIES 128
36#elif MEMORYSIZE <= 32
37#define DC_NUM_ENTRIES 48
38#define DC_MAP_NUM_ENTRIES 128
39#else /* MEMORYSIZE > 32 */
40#define DC_NUM_ENTRIES 64
41#define DC_MAP_NUM_ENTRIES 256
42#endif /* MEMORYSIZE */
43
44/* this _could_ be larger than a sector if that would ever be useful */
45#define DC_CACHE_BUFSIZE SECTOR_SIZE
46
47#include "mutex.h"
48#include "mv.h"
49
50static inline void dc_lock_cache(void)
51{
52 extern struct mutex disk_cache_mutex;
53 mutex_lock(&disk_cache_mutex);
54}
55
56static inline void dc_unlock_cache(void)
57{
58 extern struct mutex disk_cache_mutex;
59 mutex_unlock(&disk_cache_mutex);
60}
61
62void * dc_cache_probe(IF_MV(int volume,) unsigned long secnum,
63 unsigned int *flags);
64void dc_dirty_buf(void *buf);
65void dc_discard_buf(void *buf);
66void dc_commit_all(IF_MV_NONVOID(int volume));
67void dc_discard_all(IF_MV_NONVOID(int volume));
68
69void dc_init(void) INIT_ATTR;
70
71/* in addition to filling, writeback is implemented by the client */
72extern void dc_writeback_callback(IF_MV(int volume, ) unsigned long sector,
73 void *buf);
74
75
76/** These synchronize and can be called by anyone **/
77
78/* expropriate a buffer from the cache of DC_CACHE_BUFSIZE bytes */
79void * dc_get_buffer(void);
80/* return buffer to the cache by buffer */
81void dc_release_buffer(void *buf);
82
83#endif /* DISK_CACHE_H */
diff --git a/firmware/include/file.h b/firmware/include/file.h
index 77930864c7..8e5bacec0e 100644
--- a/firmware/include/file.h
+++ b/firmware/include/file.h
@@ -18,81 +18,88 @@
18 * KIND, either express or implied. 18 * KIND, either express or implied.
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21
22#ifndef _FILE_H_ 21#ifndef _FILE_H_
23#define _FILE_H_ 22#define _FILE_H_
24 23
25#include <sys/types.h> 24#include <sys/types.h>
26#include "config.h" 25#include <stdbool.h>
27#include "gcc_extensions.h"
28#include <fcntl.h> 26#include <fcntl.h>
29#ifdef WIN32 27#ifdef WIN32
30/* this has SEEK_SET et al */ 28/* this has SEEK_SET et al */
31#include <stdio.h> 29#include <stdio.h>
32#endif 30#endif
33 31#include "config.h"
32#include "gcc_extensions.h"
34 33
35#undef MAX_PATH /* this avoids problems when building simulator */ 34#undef MAX_PATH /* this avoids problems when building simulator */
36#define MAX_PATH 260 35#define MAX_PATH 260
37#define MAX_OPEN_FILES 11
38 36
39#if !defined(PLUGIN) && !defined(CODEC) 37enum relate_result
40#if defined(APPLICATION) && !defined(__PCTOOL__) 38{
41#include "rbpaths.h" 39 /* < 0 == failure */
42# define open(x, ...) app_open(x, __VA_ARGS__) 40 RELATE_DIFFERENT = 0, /* the two paths are different objects */
43# define creat(x,m) app_creat(x, m) 41 RELATE_SAME, /* the two paths are the same object */
44# define remove(x) app_remove(x) 42 RELATE_PREFIX, /* the path2 contains path1 as a prefix */
45# define rename(x,y) app_rename(x,y) 43};
46# define readlink(x,y,z) app_readlink(x,y,z)
47# if (CONFIG_PLATFORM & (PLATFORM_SDL|PLATFORM_MAEMO|PLATFORM_PANDORA))
48/* SDL overrides a few more */
49# define read(x,y,z) sim_read(x,y,z)
50# define write(x,y,z) sim_write(x,y,z)
51# endif
52#elif defined(SIMULATOR) || defined(DBTOOL)
53# define open(x, ...) sim_open(x, __VA_ARGS__)
54# define creat(x,m) sim_creat(x,m)
55# define remove(x) sim_remove(x)
56# define rename(x,y) sim_rename(x,y)
57# define fsync(x) sim_fsync(x)
58# define ftruncate(x,y) sim_ftruncate(x,y)
59# define lseek(x,y,z) sim_lseek(x,y,z)
60# define read(x,y,z) sim_read(x,y,z)
61# define write(x,y,z) sim_write(x,y,z)
62# define close(x) sim_close(x)
63/* readlink() not used in the sim yet */
64extern int sim_open(const char *name, int o, ...);
65extern int sim_creat(const char *name, mode_t mode);
66#endif
67 44
68typedef int (*open_func)(const char* pathname, int flags, ...); 45#if defined(APPLICATION)
69typedef ssize_t (*read_func)(int fd, void *buf, size_t count); 46#include "filesystem-app.h"
70typedef int (*creat_func)(const char *pathname, mode_t mode); 47#elif defined(SIMULATOR) || defined(__PCTOOL__)
71typedef ssize_t (*write_func)(int fd, const void *buf, size_t count); 48#include "../../uisimulator/common/filesystem-sim.h"
72typedef void (*qsort_func)(void *base, size_t nmemb, size_t size, 49#else
73 int(*_compar)(const void *, const void *)); 50#include "filesystem-native.h"
51#endif
74 52
75extern int file_open(const char* pathname, int flags); 53#ifndef FILEFUNCTIONS_DECLARED
76extern int close(int fd); 54int fdprintf(int fildes, const char *fmt, ...) ATTRIBUTE_PRINTF(2, 3);
77extern int fsync(int fd); 55#endif /* FILEFUNCTIONS_DECLARED */
78extern ssize_t read(int fd, void *buf, size_t count);
79extern off_t lseek(int fildes, off_t offset, int whence);
80extern int file_creat(const char *pathname);
81#if ((CONFIG_PLATFORM & PLATFORM_NATIVE) && !defined(__PCTOOL__)) || \
82 defined(TEST_FAT)
83#define creat(x, y) file_creat(x)
84 56
85#if !defined(CODEC) && !defined(PLUGIN) 57#ifndef FILEFUNCTIONS_DEFINED
86#define open(x, y, ...) file_open(x,y) 58#ifndef open
59#define open FS_PREFIX(open)
87#endif 60#endif
61#ifndef creat
62#define creat FS_PREFIX(creat)
88#endif 63#endif
89 64#ifndef close
90extern ssize_t write(int fd, const void *buf, size_t count); 65#define close FS_PREFIX(close)
91extern int remove(const char* pathname); 66#endif
92extern int rename(const char* path, const char* newname); 67#ifndef ftruncate
93extern int ftruncate(int fd, off_t length); 68#define ftruncate FS_PREFIX(ftruncate)
94extern off_t filesize(int fd); 69#endif
95extern int release_files(int volume); 70#ifndef fsync
96int fdprintf (int fd, const char *fmt, ...) ATTRIBUTE_PRINTF(2, 3); 71#define fsync FS_PREFIX(fsync)
97#endif /* !CODEC && !PLUGIN */
98#endif 72#endif
73#ifndef lseek
74#define lseek FS_PREFIX(lseek)
75#endif
76#ifndef read
77#define read FS_PREFIX(read)
78#endif
79#ifndef write
80#define write FS_PREFIX(write)
81#endif
82#ifndef remove
83#define remove FS_PREFIX(remove)
84#endif
85#ifndef rename
86#define rename FS_PREFIX(rename)
87#endif
88#ifndef filesize
89#define filesize FS_PREFIX(filesize)
90#endif
91#ifndef fsamefile
92#define fsamefile FS_PREFIX(fsamefile)
93#endif
94#ifndef file_exists
95#define file_exists FS_PREFIX(file_exists)
96#endif
97#ifndef relate
98#define relate FS_PREFIX(relate)
99#endif
100#ifndef readlink
101#define readlink FS_PREFIX(readlink)
102#endif
103#endif /* FILEFUNCTIONS_DEFINED */
104
105#endif /* _FILE_H_ */
diff --git a/firmware/include/file_internal.h b/firmware/include/file_internal.h
new file mode 100644
index 0000000000..d1bb67406a
--- /dev/null
+++ b/firmware/include/file_internal.h
@@ -0,0 +1,371 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2014 by Michael Sevakis
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef _FILE_INTERNAL_H_
22#define _FILE_INTERNAL_H_
23
24#include <sys/types.h>
25#include <stdlib.h>
26#include "mv.h"
27#include "linked_list.h"
28#include "mutex.h"
29#include "mrsw_lock.h"
30#include "fs_attr.h"
31#include "fat.h"
32#ifdef HAVE_DIRCACHE
33#include "dircache.h"
34#endif
35
36/** Tuneable parameters **/
37
38/* limits for number of open descriptors - if you increase these values, make
39 certain that the disk cache has enough available buffers */
40#define MAX_OPEN_FILES 11
41#define MAX_OPEN_DIRS 12
42#define MAX_OPEN_HANDLES (MAX_OPEN_FILES+MAX_OPEN_DIRS)
43
44/* internal functions open streams as well; make sure they don't fail if all
45 user descs are busy; this needs to be at least the greatest quantity needed
46 at once by all internal functions */
47#ifdef HAVE_DIRCACHE
48#define AUX_FILEOBJS 3
49#else
50#define AUX_FILEOBJS 2
51#endif
52
53/* number of components statically allocated to handle the vast majority
54 of path depths; should maybe be tuned for >= 90th percentile but for now,
55 imma just guessing based on something like:
56 root + 'Music' + 'Artist' + 'Album' + 'Disc N' + filename */
57#define STATIC_PATHCOMP_NUM 6
58
59#define MAX_NAME 255
60
61/* unsigned value that will also hold the off_t range we need without
62 overflow */
63#define file_size_t uint32_t
64
65#ifdef __USE_FILE_OFFSET64
66/* if we want, we can deal with files up to 2^32-1 bytes-- the full FAT16/32
67 range */
68#define FILE_SIZE_MAX (0xffffffffu)
69#else
70/* file contents and size will be preserved by the APIs so long as ftruncate()
71 isn't used; bytes passed 2^31-1 will not accessible nor will writes succeed
72 that would extend the file beyond the max for a 32-bit off_t */
73#define FILE_SIZE_MAX (0x7fffffffu)
74#endif
75
76/* if file is "large(ish)", then get rid of the contents now rather than
77 lazily when the file is synced or closed in order to free-up space */
78#define O_TRUNC_THRESH 65536
79
80/* default attributes when creating new files and directories */
81#define ATTR_NEW_FILE (ATTR_ARCHIVE)
82#define ATTR_NEW_DIRECTORY (ATTR_DIRECTORY)
83
84#define ATTR_MOUNT_POINT (ATTR_VOLUME | ATTR_DIRECTORY)
85
86/** File sector cache **/
87
88enum filestr_cache_flags
89{
90 FSC_DIRTY = 0x1, /* buffer is dirty (needs writeback) */
91 FSC_NEW = 0x2, /* buffer is new (never yet written) */
92};
93
94struct filestr_cache
95{
96 uint8_t *buffer; /* buffer to hold sector */
97 unsigned long sector; /* file sector that is in buffer */
98 unsigned int flags; /* FSC_* bits */
99};
100
101void file_cache_init(struct filestr_cache *cachep);
102void file_cache_reset(struct filestr_cache *cachep);
103void file_cache_alloc(struct filestr_cache *cachep);
104void file_cache_free(struct filestr_cache *cachep);
105
106
107/** Common bitflags used throughout **/
108
109/* bitflags used by open files and descriptors */
110enum fildes_and_obj_flags
111{
112 /* used in descriptor and common */
113 FDO_BUSY = 0x0001, /* descriptor/object is in use */
114 /* only used in individual stream descriptor */
115 FD_WRITE = 0x0002, /* descriptor has write mode */
116 FD_WRONLY = 0x0004, /* descriptor is write mode only */
117 FD_APPEND = 0x0008, /* descriptor is append mode */
118 /* only used as common flags */
119 FO_DIRECTORY = 0x0010, /* fileobj is a directory */
120 FO_TRUNC = 0x0020, /* fileobj is opened to be truncated */
121 FO_REMOVED = 0x0040, /* fileobj was deleted while open */
122 FO_SINGLE = 0x0080, /* fileobj has only one stream open */
123 FDO_MASK = 0x00ff,
124 /* bitflags that instruct various 'open' functions how to behave */
125 FF_FILE = 0x0000, /* expect file; accept file only */
126 FF_DIR = 0x0100, /* expect dir; accept dir only */
127 FF_ANYTYPE = 0x0200, /* succeed if either file or dir */
128 FF_TYPEMASK = 0x0300, /* mask of typeflags */
129 FF_CREAT = 0x0400, /* create if file doesn't exist */
130 FF_EXCL = 0x0800, /* fail if creating and file exists */
131 FF_CHECKPREFIX = 0x1000, /* detect if file is prefix of path */
132 FF_NOISO = 0x2000, /* do not decode ISO filenames to UTF-8 */
133 FF_MASK = 0x3f00,
134 /* special values used in isolation */
135 FV_NONEXIST = 0x8000, /* closed but not freed (unmounted) */
136 FV_OPENSYSROOT = 0xc001, /* open sysroot, volume 0 not mounted */
137};
138
139
140/** Common data structures used throughout **/
141
142/* basic file information about its location */
143struct file_base_info
144{
145 union {
146#ifdef HAVE_MULTIVOLUME
147 int volume; /* file's volume (overlaps fatfile.volume) */
148#endif
149#if CONFIG_PLATFORM & PLATFORM_NATIVE
150 struct fat_file fatfile; /* FS driver file info */
151#endif
152 };
153#ifdef HAVE_DIRCACHE
154 struct dircache_file dcfile; /* dircache file info */
155#endif
156};
157
158#define BASEINFO_VOL(infop) \
159 IF_MV_VOL((infop)->volume)
160
161/* open files binding item */
162struct file_base_binding
163{
164 struct ll_node node; /* list item node (first!) */
165 struct file_base_info info; /* basic file info */
166};
167
168#define BASEBINDING_VOL(bindp) \
169 BASEINFO_VOL(&(bindp)->info)
170
171/* directory scanning position info */
172struct dirscan_info
173{
174#if CONFIG_PLATFORM & PLATFORM_NATIVE
175 struct fat_dirscan_info fatscan; /* FS driver scan info */
176#endif
177#ifdef HAVE_DIRCACHE
178 struct dircache_file dcscan; /* dircache scan info */
179#endif
180};
181
182/* describes the file as an open stream */
183struct filestr_base
184{
185 struct ll_node node; /* list item node (first!) */
186 uint16_t flags; /* FD_* bits of this stream */
187 uint16_t unused; /* not used */
188 struct filestr_cache cache; /* stream-local cache */
189 struct filestr_cache *cachep; /* the cache in use (local or shared) */
190 struct file_base_info *infop; /* base file information */
191 struct fat_filestr fatstr; /* FS driver information */
192 struct file_base_binding *bindp; /* common binding for file/dir */
193 struct mutex *mtx; /* serialization for this stream */
194};
195
196void filestr_base_init(struct filestr_base *stream);
197void filestr_base_destroy(struct filestr_base *stream);
198void filestr_alloc_cache(struct filestr_base *stream);
199void filestr_free_cache(struct filestr_base *stream);
200void filestr_assign_cache(struct filestr_base *stream,
201 struct filestr_cache *cachep);
202void filestr_copy_cache(struct filestr_base *stream,
203 struct filestr_cache *cachep);
204void filestr_discard_cache(struct filestr_base *stream);
205
206/* allocates a cache buffer if needed and returns the cache pointer */
207static inline struct filestr_cache *
208filestr_get_cache(struct filestr_base *stream)
209{
210 struct filestr_cache *cachep = stream->cachep;
211
212 if (!cachep->buffer)
213 filestr_alloc_cache(stream);
214
215 return cachep;
216}
217
218static inline void filestr_lock(struct filestr_base *stream)
219{
220 mutex_lock(stream->mtx);
221}
222
223static inline void filestr_unlock(struct filestr_base *stream)
224{
225 mutex_unlock(stream->mtx);
226}
227
228/* stream lock doesn't have to be used if getting RW lock writer access */
229#define FILESTR_WRITER 0
230#define FILESTR_READER 1
231
232#define FILESTR_LOCK(type, stream) \
233 ({ if (FILESTR_##type) filestr_lock(stream); })
234
235#define FILESTR_UNLOCK(type, stream) \
236 ({ if (FILESTR_##type) filestr_unlock(stream); })
237
238#define ATTR_PREFIX (0x8000) /* out of the way of all ATTR_* bits */
239
240/* structure to return detailed information about what you opened */
241struct path_component_info
242{
243 const char *name; /* pointer to name within 'path' */
244 size_t length; /* length of component within 'path' */
245 file_size_t filesize; /* size of the opened file (0 if dir) */
246 unsigned int attr; /* attributes of this component */
247 struct file_base_info *prefixp; /* base info to check as prefix (IN) */
248 struct file_base_info parentinfo; /* parent directory info of file */
249};
250
251int open_stream_internal(const char *path, unsigned int callflags,
252 struct filestr_base *stream,
253 struct path_component_info *compinfo);
254int close_stream_internal(struct filestr_base *stream);
255int create_stream_internal(struct file_base_info *parentinfop,
256 const char *basename, size_t length,
257 unsigned int attr, unsigned int callflags,
258 struct filestr_base *stream);
259int remove_stream_internal(const char *path, struct filestr_base *stream,
260 unsigned int callflags);
261int test_stream_exists_internal(const char *path, unsigned int callflags);
262
263int open_noiso_internal(const char *path, int oflag); /* file.c */
264
265struct dirent;
266int uncached_readdir_dirent(struct filestr_base *stream,
267 struct dirscan_info *scanp,
268 struct dirent *entry);
269void uncached_rewinddir_dirent(struct dirscan_info *scanp);
270
271int uncached_readdir_internal(struct filestr_base *stream,
272 struct file_base_info *infop,
273 struct fat_direntry *fatent);
274void uncached_rewinddir_internal(struct file_base_info *infop);
275
276int test_dir_empty_internal(struct filestr_base *stream);
277
278struct dirinfo_internal
279{
280 unsigned int attr;
281 file_size_t size;
282 uint16_t wrtdate;
283 uint16_t wrttime;
284};
285
286/** Synchronization used throughout **/
287
288/* acquire the filesystem lock as READER */
289static inline void file_internal_lock_READER(void)
290{
291 extern struct mrsw_lock file_internal_mrsw;
292 mrsw_read_acquire(&file_internal_mrsw);
293}
294
295/* release the filesystem lock as READER */
296static inline void file_internal_unlock_READER(void)
297{
298 extern struct mrsw_lock file_internal_mrsw;
299 mrsw_read_release(&file_internal_mrsw);
300}
301
302/* acquire the filesystem lock as WRITER */
303static inline void file_internal_lock_WRITER(void)
304{
305 extern struct mrsw_lock file_internal_mrsw;
306 mrsw_write_acquire(&file_internal_mrsw);
307}
308
309/* release the filesystem lock as WRITER */
310static inline void file_internal_unlock_WRITER(void)
311{
312 extern struct mrsw_lock file_internal_mrsw;
313 mrsw_write_release(&file_internal_mrsw);
314}
315
316#define ERRNO 0 /* maintain errno value */
317#define RC 0 /* maintain rc value */
318
319/* NOTES: if _errno is a non-constant expression, it must set an error
320 * number and not return the ERRNO constant which will merely set
321 * errno to zero, not preserve the current value; if you must set
322 * errno to zero, set it explicitly, not in the macro
323 *
324 * if _rc is constant-expression evaluation to 'RC', then rc will
325 * NOT be altered; i.e. if you must set rc to zero, set it explicitly,
326 * not in the macro
327 */
328
329/* set errno and rc and proceed to the "file_error:" label */
330#define FILE_ERROR(_errno, _rc) \
331 ({ __builtin_constant_p(_errno) ? \
332 ({ if ((_errno) != ERRNO) errno = (_errno); }) : \
333 ({ errno = (_errno); }); \
334 __builtin_constant_p(_rc) ? \
335 ({ if ((_rc) != RC) rc = (_rc); }) : \
336 ({ rc = (_rc); }); \
337 goto file_error; })
338
339/* set errno and return a value at the point of invocation */
340#define FILE_ERROR_RETURN(_errno, _rc...) \
341 ({ __builtin_constant_p(_errno) ? \
342 ({ if ((_errno) != ERRNO) errno = (_errno); }) : \
343 ({ errno = (_errno); }); \
344 return _rc; })
345
346
347/** Misc. stuff **/
348
349/* iterate through all the volumes if volume < 0, else just the given volume */
350#define FOR_EACH_VOLUME(volume, i) \
351 for (int i = (IF_MV_VOL(volume) >= 0 ? IF_MV_VOL(volume) : 0), \
352 _end = (IF_MV_VOL(volume) >= 0 ? i : NUM_VOLUMES-1); \
353 i <= _end; i++)
354
355/* return a pointer to the static struct fat_direntry */
356static inline struct fat_direntry *get_dir_fatent(void)
357{
358 extern struct fat_direntry dir_fatent;
359 return &dir_fatent;
360}
361
362void iso_decode_d_name(char *d_name);
363
364#ifdef HAVE_DIRCACHE
365void empty_dirent(struct dirent *entry);
366void fill_dirinfo_native(struct dirinfo_native *din);
367#endif /* HAVE_DIRCACHE */
368
369void filesystem_init(void) INIT_ATTR;
370
371#endif /* _FILE_INTERNAL_H_ */
diff --git a/firmware/include/fileobj_mgr.h b/firmware/include/fileobj_mgr.h
new file mode 100644
index 0000000000..c90a59bea0
--- /dev/null
+++ b/firmware/include/fileobj_mgr.h
@@ -0,0 +1,56 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2014 by Michael Sevakis
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef _FILEOBJ_MGR_H_
22#define _FILEOBJ_MGR_H_
23
24#include "file_internal.h"
25
26void file_binding_insert_first(struct file_base_binding *bindp);
27void file_binding_insert_last(struct file_base_binding *bindp);
28void file_binding_remove(struct file_base_binding *bindp);
29void file_binding_remove_next(struct file_base_binding *prevp,
30 struct file_base_binding *bindp);
31
32void fileobj_fileop_open(struct filestr_base *stream,
33 const struct file_base_info *srcinfop,
34 unsigned int callflags);
35void fileobj_fileop_close(struct filestr_base *stream);
36void fileobj_fileop_create(struct filestr_base *stream,
37 const struct file_base_info *srcinfop,
38 unsigned int callflags);
39void fileobj_fileop_rename(struct filestr_base *stream,
40 const struct file_base_info *oldinfop);
41void fileobj_fileop_remove(struct filestr_base *stream,
42 const struct file_base_info *oldinfop);
43void fileobj_fileop_sync(struct filestr_base *stream);
44void fileobj_fileop_truncate(struct filestr_base *stream);
45extern void ftruncate_internal_callback(struct filestr_base *stream,
46 struct filestr_base *s);
47
48file_size_t * fileobj_get_sizep(const struct filestr_base *stream);
49unsigned int fileobj_get_flags(const struct filestr_base *stream);
50void fileobj_change_flags(struct filestr_base *stream,
51 unsigned int flags, unsigned int mask);
52void fileobj_mgr_unmount(IF_MV_NONVOID(int volume));
53
54void fileobj_mgr_init(void) INIT_ATTR;
55
56#endif /* _FILEOBJ_MGR_H_ */
diff --git a/firmware/include/filesystem-native.h b/firmware/include/filesystem-native.h
new file mode 100644
index 0000000000..640e179890
--- /dev/null
+++ b/firmware/include/filesystem-native.h
@@ -0,0 +1,107 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Björn Stenberg
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef _FILESYSTEM_NATIVE_H_
22#define _FILESYSTEM_NATIVE_H_
23
24#if defined(PLUGIN) || defined(CODEC)
25#define FILEFUNCTIONS_DECLARED
26#define FILEFUNCTIONS_DEFINED
27#define DIRFUNCTIONS_DECLARED
28#define DIRFUNCTIONS_DEFINED
29#endif /* PLUGIN || CODEC */
30
31#define FS_PREFIX(_x_) _x_
32#endif /* _FILESYSTEM_NATIVE_H_ */
33
34#ifdef _FILE_H_
35#ifndef _FILESYSTEM_NATIVE__FILE_H_
36#define _FILESYSTEM_NATIVE__FILE_H_
37
38#ifdef RB_FILESYSTEM_OS
39#define FILEFUNCTIONS_DEFINED
40#endif
41
42#ifndef FILEFUNCTIONS_DECLARED
43#define __OPEN_MODE_ARG
44#define __CREAT_MODE_ARG
45
46int open(const char *name, int oflag);
47int creat(const char *name);
48int close(int fildes);
49int ftruncate(int fildes, off_t length);
50int fsync(int fildes);
51off_t lseek(int fildes, off_t offset, int whence);
52ssize_t read(int fildes, void *buf, size_t nbyte);
53ssize_t write(int fildes, const void *buf, size_t nbyte);
54int remove(const char *path);
55int rename(const char *old, const char *new);
56off_t filesize(int fildes);
57int fsamefile(int fildes1, int fildes2);
58int relate(const char *path1, const char *path2);
59bool file_exists(const char *path);
60#endif /* !FILEFUNCTIONS_DECLARED */
61
62#if !defined(RB_FILESYSTEM_OS) && !defined (FILEFUNCTIONS_DEFINED)
63#define open(path, oflag, ...) open(path, oflag)
64#define creat(path, mode) creat(path)
65#endif /* FILEFUNCTIONS_DEFINED */
66
67#endif /* _FILESYSTEM_NATIVE__FILE_H_ */
68#endif /* _FILE_H_ */
69
70#ifdef _DIR_H_
71#ifndef _FILESYSTEM_NATIVE__DIR_H_
72#define _FILESYSTEM_NATIVE__DIR_H_
73
74#define DIRENT dirent
75struct dirent;
76
77struct dirinfo_native
78{
79 unsigned int attr;
80 off_t size;
81 uint16_t wrtdate;
82 uint16_t wrttime;
83};
84
85typedef struct {} DIR;
86
87#ifndef DIRFUNCTIONS_DECLARED
88#define __MKDIR_MODE_ARG
89
90#ifdef RB_FILESYSTEM_OS
91#define DIRFUNCTIONS_DEFINED
92#endif
93
94DIR * opendir(const char *dirname);
95struct dirent * readdir(DIR *dirp);
96int readdir_r(DIR *dirp, struct dirent *entry,
97 struct dirent **result);
98void rewinddir(DIR *dirp);
99int closedir(DIR *dirp);
100int mkdir(const char *path);
101int rmdir(const char *path);
102int samedir(DIR *dirp1, DIR *dirp2);
103bool dir_exists(const char *dirname);
104#endif /* !DIRFUNCTIONS_DECLARED */
105
106#endif /* _FILESYSTEM_NATIVE__DIR_H_ */
107#endif /* _DIR_H_ */
diff --git a/firmware/include/fs_attr.h b/firmware/include/fs_attr.h
new file mode 100644
index 0000000000..0e1d25e1de
--- /dev/null
+++ b/firmware/include/fs_attr.h
@@ -0,0 +1,39 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 by Kévin Ferrare
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21#ifndef _FS_ATTR_H_
22#define _FS_ATTR_H_
23
24#include <stdbool.h>
25
26#undef MAX_PATH /* this avoids problems when building simulator */
27#define MAX_PATH 260
28
29/* also used by fat.c so values must not change */
30#define ATTR_READ_ONLY 0x01
31#define ATTR_HIDDEN 0x02
32#define ATTR_SYSTEM 0x04
33#define ATTR_VOLUME_ID 0x08
34#define ATTR_DIRECTORY 0x10
35#define ATTR_ARCHIVE 0x20
36#define ATTR_VOLUME 0x40 /* this is a volume, not a real directory */
37#define ATTR_LINK 0x80
38
39#endif /* _FS_ATTR_H_ */
diff --git a/firmware/include/rb-loader.h b/firmware/include/rb-loader.h
index e1e756dba9..86c5026af9 100644
--- a/firmware/include/rb-loader.h
+++ b/firmware/include/rb-loader.h
@@ -18,5 +18,4 @@
18 * 18 *
19 ****************************************************************************/ 19 ****************************************************************************/
20 20
21const char *rb_strerror(int8_t errno);
22int load_firmware(unsigned char* buf, const char* firmware, int buffer_size); 21int load_firmware(unsigned char* buf, const char* firmware, int buffer_size);
diff --git a/firmware/include/rbunicode.h b/firmware/include/rbunicode.h
index 3c28b3031e..077029304d 100644
--- a/firmware/include/rbunicode.h
+++ b/firmware/include/rbunicode.h
@@ -51,7 +51,8 @@ enum codepages {
51 KSX_1001, /* Korean */ 51 KSX_1001, /* Korean */
52 BIG_5, /* Trad. Chinese */ 52 BIG_5, /* Trad. Chinese */
53 UTF_8, /* Unicode */ 53 UTF_8, /* Unicode */
54 NUM_CODEPAGES 54 NUM_CODEPAGES,
55 INIT_CODEPAGE = ISO_8859_1,
55}; 56};
56 57
57#else /* !HAVE_LCD_BITMAP, reduced support */ 58#else /* !HAVE_LCD_BITMAP, reduced support */
@@ -65,7 +66,8 @@ enum codepages {
65 WIN_1250, /* Central European */ 66 WIN_1250, /* Central European */
66 WIN_1252, /* Western European */ 67 WIN_1252, /* Western European */
67 UTF_8, /* Unicode */ 68 UTF_8, /* Unicode */
68 NUM_CODEPAGES 69 NUM_CODEPAGES,
70 INIT_CODEPAGE = ISO_8859_1,
69}; 71};
70 72
71#endif 73#endif
@@ -78,9 +80,19 @@ unsigned char* utf16BEdecode(const unsigned char *utf16, unsigned char *utf8, in
78unsigned long utf8length(const unsigned char *utf8); 80unsigned long utf8length(const unsigned char *utf8);
79const unsigned char* utf8decode(const unsigned char *utf8, unsigned short *ucs); 81const unsigned char* utf8decode(const unsigned char *utf8, unsigned short *ucs);
80void set_codepage(int cp); 82void set_codepage(int cp);
83int get_codepage(void);
81int utf8seek(const unsigned char* utf8, int offset); 84int utf8seek(const unsigned char* utf8, int offset);
82const char* get_codepage_name(int cp); 85const char* get_codepage_name(int cp);
83#if defined(APPLICATION) && defined(__linux__) 86#ifdef APPLICATION
87#if defined(__linux__)
84const char *get_current_codepage_name_linux(void); 88const char *get_current_codepage_name_linux(void);
85#endif 89#endif
90#endif /* APPLICATION */
91
92#if 0 /* not needed just now */
93void unicode_init(void);
94#else
95#define unicode_init() do {} while (0)
96#endif
97
86#endif /* _RBUNICODE_H_ */ 98#endif /* _RBUNICODE_H_ */