diff options
Diffstat (limited to 'firmware/include')
-rw-r--r-- | firmware/include/dircache.h | 40 | ||||
-rw-r--r-- | firmware/include/dircache_redirect.h | 19 | ||||
-rw-r--r-- | firmware/include/file_internal.h | 91 | ||||
-rw-r--r-- | firmware/include/fileobj_mgr.h | 5 |
4 files changed, 104 insertions, 51 deletions
diff --git a/firmware/include/dircache.h b/firmware/include/dircache.h index 7e8c764e7f..d73c6f6e81 100644 --- a/firmware/include/dircache.h +++ b/firmware/include/dircache.h | |||
@@ -57,6 +57,15 @@ | |||
57 | figure pessimistic */ | 57 | figure pessimistic */ |
58 | typedef uint32_t dc_serial_t; | 58 | typedef uint32_t dc_serial_t; |
59 | 59 | ||
60 | /* these should agree with size of dc_serial_t */ | ||
61 | #define DC_SERHASH_START 0xffffffff | ||
62 | |||
63 | /* I was originally using FNV hash but decided this is probably okay | ||
64 | (for now) */ | ||
65 | #define dc_hash_serialnum(s, h) \ | ||
66 | ({ dc_serial_t __x = (s); crc_32(&(__x), sizeof(dc_serial_t), (h)); }) | ||
67 | #define DC_SERIAL_FMT "0x%08lX" | ||
68 | |||
60 | /** | 69 | /** |
61 | ****************************************************************************/ | 70 | ****************************************************************************/ |
62 | 71 | ||
@@ -132,10 +141,33 @@ void dircache_fileop_sync(struct file_base_binding *infop, | |||
132 | const struct dirinfo_native *dinp); | 141 | const struct dirinfo_native *dinp); |
133 | 142 | ||
134 | 143 | ||
135 | /** Dircache paths and files **/ | 144 | /** Dircache paths, files and shortcuts **/ |
136 | ssize_t dircache_get_path(const struct dircache_file *dcfilep, char *buf, | 145 | struct dircache_fileref |
137 | size_t size); | 146 | { |
138 | int dircache_get_file(const char *path, struct dircache_file *dcfilep); | 147 | struct dircache_file dcfile; |
148 | dc_serial_t serialhash; /* Hash of serialnumbers to root */ | ||
149 | }; | ||
150 | |||
151 | void dircache_fileref_init(struct dircache_fileref *dcfrefp); | ||
152 | ssize_t dircache_get_fileref_path(const struct dircache_fileref *dcfrefp, | ||
153 | char *buf, size_t size); | ||
154 | |||
155 | /* Bitflags for dircache_search() */ | ||
156 | enum dircache_search_flags | ||
157 | { | ||
158 | DCS_FILEREF = 0x01, /* Check fileref existence and serial number */ | ||
159 | _DCS_VERIFY_FLAG = 0x02, /* Internal: Only valid with DCS_FILEREF */ | ||
160 | DCS_FILEREF_VERIFY = 0x03, /* Do DCS_FILEREF check + verify serial hash */ | ||
161 | DCS_CACHED_PATH = 0x04, /* Check only cache for provided path */ | ||
162 | _DCS_STORAGE_FLAG = 0x08, /* Internal: Only valid with DCS_CACHED_PATH */ | ||
163 | DCS_STORAGE_PATH = 0x0c, /* Read-through if needed for provided path */ | ||
164 | DCS_UPDATE_FILEREF = 0x10, /* If fileref is not valid but path is found or | ||
165 | searching a path, update the reference | ||
166 | information */ | ||
167 | }; | ||
168 | |||
169 | int dircache_search(unsigned int flags, struct dircache_fileref *dcfrefp, | ||
170 | const char *path); | ||
139 | 171 | ||
140 | 172 | ||
141 | /** Debug screen/info stuff **/ | 173 | /** Debug screen/info stuff **/ |
diff --git a/firmware/include/dircache_redirect.h b/firmware/include/dircache_redirect.h index 15fb4bc38d..9fae16b551 100644 --- a/firmware/include/dircache_redirect.h +++ b/firmware/include/dircache_redirect.h | |||
@@ -24,6 +24,8 @@ | |||
24 | 24 | ||
25 | /*** | 25 | /*** |
26 | ** Internal redirects that depend upon whether or not dircache is made | 26 | ** Internal redirects that depend upon whether or not dircache is made |
27 | ** | ||
28 | ** Some stuff deals with it, some doesn't right now. This is a nexus point.. | ||
27 | **/ | 29 | **/ |
28 | 30 | ||
29 | /** File binding **/ | 31 | /** File binding **/ |
@@ -119,11 +121,6 @@ static inline void fileop_onsync_internal(struct filestr_base *stream) | |||
119 | #endif | 121 | #endif |
120 | } | 122 | } |
121 | 123 | ||
122 | static inline void fileop_ontruncate_internal(struct filestr_base *stream) | ||
123 | { | ||
124 | fileobj_fileop_truncate(stream); | ||
125 | } | ||
126 | |||
127 | static inline void volume_onmount_internal(IF_MV_NONVOID(int volume)) | 124 | static inline void volume_onmount_internal(IF_MV_NONVOID(int volume)) |
128 | { | 125 | { |
129 | #ifdef HAVE_DIRCACHE | 126 | #ifdef HAVE_DIRCACHE |
@@ -134,10 +131,20 @@ static inline void volume_onmount_internal(IF_MV_NONVOID(int volume)) | |||
134 | 131 | ||
135 | static inline void volume_onunmount_internal(IF_MV_NONVOID(int volume)) | 132 | static inline void volume_onunmount_internal(IF_MV_NONVOID(int volume)) |
136 | { | 133 | { |
137 | fileobj_mgr_unmount(IF_MV(volume)); | ||
138 | #ifdef HAVE_DIRCACHE | 134 | #ifdef HAVE_DIRCACHE |
135 | /* First, to avoid update of something about to be destroyed anyway */ | ||
139 | dircache_unmount(IF_MV(volume)); | 136 | dircache_unmount(IF_MV(volume)); |
140 | #endif | 137 | #endif |
138 | fileobj_mgr_unmount(IF_MV(volume)); | ||
139 | } | ||
140 | |||
141 | static inline void fileop_onunmount_internal(struct filestr_base *stream) | ||
142 | { | ||
143 | |||
144 | if (stream->flags & FD_WRITE) | ||
145 | force_close_writer_internal(stream); /* try to save stuff */ | ||
146 | else | ||
147 | fileop_onclose_internal(stream); /* just readers, bye */ | ||
141 | } | 148 | } |
142 | 149 | ||
143 | 150 | ||
diff --git a/firmware/include/file_internal.h b/firmware/include/file_internal.h index d1bb67406a..acec81206e 100644 --- a/firmware/include/file_internal.h +++ b/firmware/include/file_internal.h | |||
@@ -81,6 +81,7 @@ | |||
81 | #define ATTR_NEW_FILE (ATTR_ARCHIVE) | 81 | #define ATTR_NEW_FILE (ATTR_ARCHIVE) |
82 | #define ATTR_NEW_DIRECTORY (ATTR_DIRECTORY) | 82 | #define ATTR_NEW_DIRECTORY (ATTR_DIRECTORY) |
83 | 83 | ||
84 | #define ATTR_SYSTEM_ROOT (ATTR_SYSROOT | ATTR_DIRECTORY) | ||
84 | #define ATTR_MOUNT_POINT (ATTR_VOLUME | ATTR_DIRECTORY) | 85 | #define ATTR_MOUNT_POINT (ATTR_VOLUME | ATTR_DIRECTORY) |
85 | 86 | ||
86 | /** File sector cache **/ | 87 | /** File sector cache **/ |
@@ -110,33 +111,35 @@ void file_cache_free(struct filestr_cache *cachep); | |||
110 | enum fildes_and_obj_flags | 111 | enum fildes_and_obj_flags |
111 | { | 112 | { |
112 | /* used in descriptor and common */ | 113 | /* used in descriptor and common */ |
113 | FDO_BUSY = 0x0001, /* descriptor/object is in use */ | 114 | FDO_BUSY = 0x0001, /* descriptor/object is in use */ |
114 | /* only used in individual stream descriptor */ | 115 | /* only used in individual stream descriptor */ |
115 | FD_WRITE = 0x0002, /* descriptor has write mode */ | 116 | FD_WRITE = 0x0002, /* descriptor has write mode */ |
116 | FD_WRONLY = 0x0004, /* descriptor is write mode only */ | 117 | FD_WRONLY = 0x0004, /* descriptor is write mode only */ |
117 | FD_APPEND = 0x0008, /* descriptor is append mode */ | 118 | FD_APPEND = 0x0008, /* descriptor is append mode */ |
119 | FD_NONEXIST = 0x8000, /* closed but not freed (uncombined) */ | ||
118 | /* only used as common flags */ | 120 | /* only used as common flags */ |
119 | FO_DIRECTORY = 0x0010, /* fileobj is a directory */ | 121 | FO_DIRECTORY = 0x0010, /* fileobj is a directory */ |
120 | FO_TRUNC = 0x0020, /* fileobj is opened to be truncated */ | 122 | FO_TRUNC = 0x0020, /* fileobj is opened to be truncated */ |
121 | FO_REMOVED = 0x0040, /* fileobj was deleted while open */ | 123 | FO_REMOVED = 0x0040, /* fileobj was deleted while open */ |
122 | FO_SINGLE = 0x0080, /* fileobj has only one stream open */ | 124 | FO_SINGLE = 0x0080, /* fileobj has only one stream open */ |
123 | FDO_MASK = 0x00ff, | 125 | FDO_MASK = 0x00ff, |
124 | /* bitflags that instruct various 'open' functions how to behave */ | 126 | FDO_CHG_MASK = FO_TRUNC, /* fileobj permitted external change */ |
125 | FF_FILE = 0x0000, /* expect file; accept file only */ | 127 | /* bitflags that instruct various 'open' functions how to behave; |
126 | FF_DIR = 0x0100, /* expect dir; accept dir only */ | 128 | * saved in stream flags (only) but not used by manager */ |
127 | FF_ANYTYPE = 0x0200, /* succeed if either file or dir */ | 129 | FF_FILE = 0x00000000, /* expect file; accept file only */ |
128 | FF_TYPEMASK = 0x0300, /* mask of typeflags */ | 130 | FF_DIR = 0x00010000, /* expect dir; accept dir only */ |
129 | FF_CREAT = 0x0400, /* create if file doesn't exist */ | 131 | FF_ANYTYPE = 0x00020000, /* succeed if either file or dir */ |
130 | FF_EXCL = 0x0800, /* fail if creating and file exists */ | 132 | FF_TYPEMASK = 0x00030000, /* mask of typeflags */ |
131 | FF_CHECKPREFIX = 0x1000, /* detect if file is prefix of path */ | 133 | FF_CREAT = 0x00040000, /* create if file doesn't exist */ |
132 | FF_NOISO = 0x2000, /* do not decode ISO filenames to UTF-8 */ | 134 | FF_EXCL = 0x00080000, /* fail if creating and file exists */ |
133 | FF_MASK = 0x3f00, | 135 | FF_CHECKPREFIX = 0x00100000, /* detect if file is prefix of path */ |
134 | /* special values used in isolation */ | 136 | FF_NOISO = 0x00200000, /* do not decode ISO filenames to UTF-8 */ |
135 | FV_NONEXIST = 0x8000, /* closed but not freed (unmounted) */ | 137 | FF_PROBE = 0x00400000, /* only test existence; don't open */ |
136 | FV_OPENSYSROOT = 0xc001, /* open sysroot, volume 0 not mounted */ | 138 | FF_CACHEONLY = 0x00800000, /* succeed only if in dircache */ |
139 | FF_SELFINFO = 0x01000000, /* return info on self as well */ | ||
140 | FF_MASK = 0x01ff0000, | ||
137 | }; | 141 | }; |
138 | 142 | ||
139 | |||
140 | /** Common data structures used throughout **/ | 143 | /** Common data structures used throughout **/ |
141 | 144 | ||
142 | /* basic file information about its location */ | 145 | /* basic file information about its location */ |
@@ -183,8 +186,7 @@ struct dirscan_info | |||
183 | struct filestr_base | 186 | struct filestr_base |
184 | { | 187 | { |
185 | struct ll_node node; /* list item node (first!) */ | 188 | struct ll_node node; /* list item node (first!) */ |
186 | uint16_t flags; /* FD_* bits of this stream */ | 189 | uint32_t flags; /* F[DF]_* bits of this stream */ |
187 | uint16_t unused; /* not used */ | ||
188 | struct filestr_cache cache; /* stream-local cache */ | 190 | struct filestr_cache cache; /* stream-local cache */ |
189 | struct filestr_cache *cachep; /* the cache in use (local or shared) */ | 191 | struct filestr_cache *cachep; /* the cache in use (local or shared) */ |
190 | struct file_base_info *infop; /* base file information */ | 192 | struct file_base_info *infop; /* base file information */ |
@@ -235,17 +237,25 @@ static inline void filestr_unlock(struct filestr_base *stream) | |||
235 | #define FILESTR_UNLOCK(type, stream) \ | 237 | #define FILESTR_UNLOCK(type, stream) \ |
236 | ({ if (FILESTR_##type) filestr_unlock(stream); }) | 238 | ({ if (FILESTR_##type) filestr_unlock(stream); }) |
237 | 239 | ||
238 | #define ATTR_PREFIX (0x8000) /* out of the way of all ATTR_* bits */ | 240 | /* auxilliary attributes - out of the way of regular ATTR_* bits */ |
241 | #define ATTR_SYSROOT (0x8000) | ||
242 | #define ATTR_PREFIX (0x4000) | ||
239 | 243 | ||
240 | /* structure to return detailed information about what you opened */ | 244 | /* structure to return detailed information about what you opened */ |
241 | struct path_component_info | 245 | struct path_component_info |
242 | { | 246 | { |
243 | const char *name; /* pointer to name within 'path' */ | 247 | const char *name; /* pointer to name within 'path' (OUT) */ |
244 | size_t length; /* length of component within 'path' */ | 248 | size_t length; /* length of component within 'path' */ |
245 | file_size_t filesize; /* size of the opened file (0 if dir) */ | 249 | file_size_t filesize; /* size of the opened file (0 if dir) */ |
246 | unsigned int attr; /* attributes of this component */ | 250 | unsigned int attr; /* attributes of this component */ |
247 | struct file_base_info *prefixp; /* base info to check as prefix (IN) */ | 251 | struct file_base_info *prefixp; /* base info to check as prefix |
248 | struct file_base_info parentinfo; /* parent directory info of file */ | 252 | (IN if FF_CHECKPREFIX) */ |
253 | union { | ||
254 | struct file_base_info parentinfo; /* parent directory base info of file | ||
255 | (if not FF_SELFINFO) */ | ||
256 | struct file_base_info info; /* base info of file itself | ||
257 | (if FF_SELFINFO) */ | ||
258 | }; | ||
249 | }; | 259 | }; |
250 | 260 | ||
251 | int open_stream_internal(const char *path, unsigned int callflags, | 261 | int open_stream_internal(const char *path, unsigned int callflags, |
@@ -261,6 +271,7 @@ int remove_stream_internal(const char *path, struct filestr_base *stream, | |||
261 | int test_stream_exists_internal(const char *path, unsigned int callflags); | 271 | int test_stream_exists_internal(const char *path, unsigned int callflags); |
262 | 272 | ||
263 | int open_noiso_internal(const char *path, int oflag); /* file.c */ | 273 | int open_noiso_internal(const char *path, int oflag); /* file.c */ |
274 | void force_close_writer_internal(struct filestr_base *stream); /* file.c */ | ||
264 | 275 | ||
265 | struct dirent; | 276 | struct dirent; |
266 | int uncached_readdir_dirent(struct filestr_base *stream, | 277 | int uncached_readdir_dirent(struct filestr_base *stream, |
@@ -326,22 +337,26 @@ static inline void file_internal_unlock_WRITER(void) | |||
326 | * not in the macro | 337 | * not in the macro |
327 | */ | 338 | */ |
328 | 339 | ||
340 | #define FILE_SET_CODE(_name, _keepcode, _value) \ | ||
341 | ({ __builtin_constant_p(_value) ? \ | ||
342 | ({ if ((_value) != (_keepcode)) _name = (_value); }) : \ | ||
343 | ({ _name = (_value); }); }) | ||
344 | |||
329 | /* set errno and rc and proceed to the "file_error:" label */ | 345 | /* set errno and rc and proceed to the "file_error:" label */ |
330 | #define FILE_ERROR(_errno, _rc) \ | 346 | #define FILE_ERROR(_errno, _rc) \ |
331 | ({ __builtin_constant_p(_errno) ? \ | 347 | ({ FILE_SET_CODE(errno, ERRNO, (_errno)); \ |
332 | ({ if ((_errno) != ERRNO) errno = (_errno); }) : \ | 348 | FILE_SET_CODE(rc, RC, (_rc)); \ |
333 | ({ errno = (_errno); }); \ | ||
334 | __builtin_constant_p(_rc) ? \ | ||
335 | ({ if ((_rc) != RC) rc = (_rc); }) : \ | ||
336 | ({ rc = (_rc); }); \ | ||
337 | goto file_error; }) | 349 | goto file_error; }) |
338 | 350 | ||
339 | /* set errno and return a value at the point of invocation */ | 351 | /* set errno and return a value at the point of invocation */ |
340 | #define FILE_ERROR_RETURN(_errno, _rc...) \ | 352 | #define FILE_ERROR_RETURN(_errno, _rc...) \ |
341 | ({ __builtin_constant_p(_errno) ? \ | 353 | ({ FILE_SET_CODE(errno, ERRNO, _errno); \ |
342 | ({ if ((_errno) != ERRNO) errno = (_errno); }) : \ | 354 | return _rc; }) |
343 | ({ errno = (_errno); }); \ | 355 | |
344 | return _rc; }) | 356 | /* set errno and return code, no branching */ |
357 | #define FILE_ERROR_SET(_errno, _rc) \ | ||
358 | ({ FILE_SET_CODE(errno, ERRNO, (_errno)); \ | ||
359 | FILE_SET_CODE(rc, RC, (_rc)); }) | ||
345 | 360 | ||
346 | 361 | ||
347 | /** Misc. stuff **/ | 362 | /** Misc. stuff **/ |
diff --git a/firmware/include/fileobj_mgr.h b/firmware/include/fileobj_mgr.h index c90a59bea0..627d2df341 100644 --- a/firmware/include/fileobj_mgr.h +++ b/firmware/include/fileobj_mgr.h | |||
@@ -41,12 +41,11 @@ void fileobj_fileop_rename(struct filestr_base *stream, | |||
41 | void fileobj_fileop_remove(struct filestr_base *stream, | 41 | void fileobj_fileop_remove(struct filestr_base *stream, |
42 | const struct file_base_info *oldinfop); | 42 | const struct file_base_info *oldinfop); |
43 | void fileobj_fileop_sync(struct filestr_base *stream); | 43 | void fileobj_fileop_sync(struct filestr_base *stream); |
44 | void fileobj_fileop_truncate(struct filestr_base *stream); | ||
45 | extern void ftruncate_internal_callback(struct filestr_base *stream, | ||
46 | struct filestr_base *s); | ||
47 | 44 | ||
48 | file_size_t * fileobj_get_sizep(const struct filestr_base *stream); | 45 | file_size_t * fileobj_get_sizep(const struct filestr_base *stream); |
49 | unsigned int fileobj_get_flags(const struct filestr_base *stream); | 46 | unsigned int fileobj_get_flags(const struct filestr_base *stream); |
47 | struct filestr_base * fileobj_get_next_stream(const struct filestr_base *stream, | ||
48 | const struct filestr_base *s); | ||
50 | void fileobj_change_flags(struct filestr_base *stream, | 49 | void fileobj_change_flags(struct filestr_base *stream, |
51 | unsigned int flags, unsigned int mask); | 50 | unsigned int flags, unsigned int mask); |
52 | void fileobj_mgr_unmount(IF_MV_NONVOID(int volume)); | 51 | void fileobj_mgr_unmount(IF_MV_NONVOID(int volume)); |