summaryrefslogtreecommitdiff
path: root/firmware/common/dir_uncached.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/common/dir_uncached.c')
-rw-r--r--firmware/common/dir_uncached.c312
1 files changed, 0 insertions, 312 deletions
diff --git a/firmware/common/dir_uncached.c b/firmware/common/dir_uncached.c
deleted file mode 100644
index b850a514e7..0000000000
--- a/firmware/common/dir_uncached.c
+++ /dev/null
@@ -1,312 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: dir.c 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#include <stdio.h>
22#include <errno.h>
23#include <string.h>
24#include <stdbool.h>
25#include <stdlib.h>
26#include "fat.h"
27#include "dir.h"
28#include "debug.h"
29#include "filefuncs.h"
30
31#if (MEMORYSIZE > 8)
32#define MAX_OPEN_DIRS 12
33#else
34#define MAX_OPEN_DIRS 8
35#endif
36
37static DIR_UNCACHED opendirs[MAX_OPEN_DIRS];
38
39// release all dir handles on a given volume "by force", to avoid leaks
40int release_dirs(int volume)
41{
42 DIR_UNCACHED* pdir = opendirs;
43 int dd;
44 int closed = 0;
45 for ( dd=0; dd<MAX_OPEN_DIRS; dd++, pdir++)
46 {
47#ifdef HAVE_MULTIVOLUME
48 if (pdir->fatdir.file.volume == volume)
49#else
50 (void)volume;
51#endif
52 {
53 pdir->busy = false; /* mark as available, no further action */
54 closed++;
55 }
56 }
57 return closed; /* return how many we did */
58}
59
60DIR_UNCACHED* opendir_uncached(const char* name)
61{
62 char namecopy[MAX_PATH];
63 char* part;
64 char* end;
65 struct fat_direntry entry;
66 int dd;
67 DIR_UNCACHED* pdir = opendirs;
68#ifdef HAVE_MULTIVOLUME
69 int volume;
70#endif
71
72 if ( name[0] != '/' ) {
73 DEBUGF("Only absolute paths supported right now\n");
74 return NULL;
75 }
76
77 /* find a free dir descriptor */
78 for ( dd=0; dd<MAX_OPEN_DIRS; dd++, pdir++)
79 if ( !pdir->busy )
80 break;
81
82 if ( dd == MAX_OPEN_DIRS ) {
83 DEBUGF("Too many dirs open\n");
84 errno = EMFILE;
85 return NULL;
86 }
87
88 pdir->busy = true;
89
90#ifdef HAVE_MULTIVOLUME
91 /* try to extract a heading volume name, if present */
92 volume = strip_volume(name, namecopy);
93 pdir->volumecounter = 0;
94#else
95 strlcpy(namecopy, name, sizeof(namecopy)); /* just copy */
96#endif
97
98 if ( fat_opendir(IF_MV(volume,) &pdir->fatdir, 0, NULL) < 0 ) {
99 DEBUGF("Failed opening root dir\n");
100 pdir->busy = false;
101 return NULL;
102 }
103
104 for ( part = strtok_r(namecopy, "/", &end); part;
105 part = strtok_r(NULL, "/", &end)) {
106 /* scan dir for name */
107 while (1) {
108 if ((fat_getnext(&pdir->fatdir,&entry) < 0) ||
109 (!entry.name[0])) {
110 pdir->busy = false;
111 return NULL;
112 }
113 if ( (entry.attr & FAT_ATTR_DIRECTORY) &&
114 (!strcasecmp(part, entry.name)) ) {
115 /* In reality, the parent_dir parameter of fat_opendir seems
116 * useless because it's sole purpose it to have a way to
117 * update the file metadata, but here we are only reading
118 * a directory so there's no need for that kind of stuff.
119 * However, the rmdir_uncached function uses a ugly hack to
120 * avoid opening a directory twice when deleting it and thus
121 * needs those information. That's why we pass pdir->fatdir both
122 * as the parent directory and the resulting one (this is safe,
123 * in doubt, check fat_open(dir) code) which will allow this kind of
124 * (ugly) things */
125 if ( fat_opendir(IF_MV(volume,)
126 &pdir->fatdir,
127 entry.firstcluster,
128 &pdir->fatdir) < 0 ) {
129 DEBUGF("Failed opening dir '%s' (%ld)\n",
130 part, entry.firstcluster);
131 pdir->busy = false;
132 return NULL;
133 }
134#ifdef HAVE_MULTIVOLUME
135 pdir->volumecounter = -1; /* n.a. to subdirs */
136#endif
137 break;
138 }
139 }
140 }
141
142 return pdir;
143}
144
145int closedir_uncached(DIR_UNCACHED* dir)
146{
147 dir->busy=false;
148 return 0;
149}
150
151struct dirent_uncached* readdir_uncached(DIR_UNCACHED* dir)
152{
153 struct fat_direntry entry;
154 struct dirent_uncached* theent = &(dir->theent);
155
156 if (!dir->busy)
157 return NULL;
158
159#ifdef HAVE_MULTIVOLUME
160 /* Volumes (secondary file systems) get inserted into the root directory
161 of the first volume, since we have no separate top level. */
162 if (dir->volumecounter >= 0 /* on a root dir */
163 && dir->volumecounter < NUM_VOLUMES /* in range */
164 && dir->fatdir.file.volume == 0) /* at volume 0 */
165 { /* fake special directories, which don't really exist, but
166 will get redirected upon opendir_uncached() */
167 while (++dir->volumecounter < NUM_VOLUMES)
168 {
169 if (fat_ismounted(dir->volumecounter))
170 {
171 memset(theent, 0, sizeof(*theent));
172 theent->info.attribute = FAT_ATTR_DIRECTORY | FAT_ATTR_VOLUME;
173 snprintf(theent->d_name, sizeof(theent->d_name),
174 VOL_NAMES, dir->volumecounter);
175 return theent;
176 }
177 }
178 }
179#endif
180 /* normal directory entry fetching follows here */
181 if (fat_getnext(&(dir->fatdir),&entry) < 0)
182 return NULL;
183
184 if ( !entry.name[0] )
185 return NULL;
186
187 strlcpy(theent->d_name, entry.name, sizeof(theent->d_name));
188 theent->info.attribute = entry.attr;
189 theent->info.wrtdate = entry.wrtdate;
190 theent->info.wrttime = entry.wrttime;
191 theent->info.size = entry.filesize;
192 theent->startcluster = entry.firstcluster;
193
194 return theent;
195}
196
197int mkdir_uncached(const char *name)
198{
199 DIR_UNCACHED *dir;
200 char namecopy[MAX_PATH];
201 char* end;
202 char *basename;
203 char *parent;
204 struct dirent_uncached *entry;
205 int dd;
206 DIR_UNCACHED* pdir = opendirs;
207 struct fat_dir *newdir;
208 int rc;
209
210 if ( name[0] != '/' ) {
211 DEBUGF("mkdir: Only absolute paths supported right now\n");
212 return -1;
213 }
214 /* find a free dir descriptor */
215 for ( dd=0; dd<MAX_OPEN_DIRS; dd++, pdir++)
216 if ( !pdir->busy )
217 break;
218
219 if ( dd == MAX_OPEN_DIRS ) {
220 DEBUGF("Too many dirs open\n");
221 errno = EMFILE;
222 return -5;
223 }
224
225 pdir->busy = true;
226 newdir = &pdir->fatdir;
227
228 strlcpy(namecopy, name, sizeof(namecopy));
229
230 /* Split the base name and the path */
231 end = strrchr(namecopy, '/');
232 *end = 0;
233 basename = end+1;
234
235 if(namecopy == end) /* Root dir? */
236 parent = "/";
237 else
238 parent = namecopy;
239
240 DEBUGF("mkdir: parent: %s, name: %s\n", parent, basename);
241
242 dir = opendir_uncached(parent);
243
244 if(!dir) {
245 DEBUGF("mkdir: can't open parent dir\n");
246 pdir->busy = false;
247 return -2;
248 }
249
250 if(basename[0] == 0) {
251 DEBUGF("mkdir: Empty dir name\n");
252 pdir->busy = false;
253 errno = EINVAL;
254 return -3;
255 }
256
257 /* Now check if the name already exists */
258 while ((entry = readdir_uncached(dir))) {
259 if ( !strcasecmp(basename, entry->d_name) ) {
260 DEBUGF("mkdir error: file exists\n");
261 errno = EEXIST;
262 closedir_uncached(dir);
263 pdir->busy = false;
264 return - 4;
265 }
266 }
267
268 memset(newdir, 0, sizeof(struct fat_dir));
269
270 rc = fat_create_dir(basename, newdir, &(dir->fatdir));
271 closedir_uncached(dir);
272 pdir->busy = false;
273
274 return rc;
275}
276
277int rmdir_uncached(const char* name)
278{
279 int rc;
280 DIR_UNCACHED* dir;
281 struct dirent_uncached* entry;
282
283 dir = opendir_uncached(name);
284 if (!dir)
285 {
286 errno = ENOENT; /* open error */
287 return -1;
288 }
289
290 /* check if the directory is empty */
291 while ((entry = readdir_uncached(dir)))
292 {
293 if (strcmp(entry->d_name, ".") &&
294 strcmp(entry->d_name, ".."))
295 {
296 DEBUGF("rmdir error: not empty\n");
297 errno = ENOTEMPTY;
298 closedir_uncached(dir);
299 return -2;
300 }
301 }
302
303 rc = fat_remove(&(dir->fatdir.file));
304 if ( rc < 0 ) {
305 DEBUGF("Failed removing dir: %d\n", rc);
306 errno = EIO;
307 rc = rc * 10 - 3;
308 }
309
310 closedir_uncached(dir);
311 return rc;
312}