diff options
Diffstat (limited to 'firmware/common')
-rw-r--r-- | firmware/common/dir.c | 1 | ||||
-rw-r--r-- | firmware/common/dir.h | 1 | ||||
-rw-r--r-- | firmware/common/file.c | 170 | ||||
-rw-r--r-- | firmware/common/file.h | 7 |
4 files changed, 176 insertions, 3 deletions
diff --git a/firmware/common/dir.c b/firmware/common/dir.c index b0927c09c6..acc412c570 100644 --- a/firmware/common/dir.c +++ b/firmware/common/dir.c | |||
@@ -94,6 +94,7 @@ struct dirent* readdir(DIR* dir) | |||
94 | strncpy(theent.d_name, entry.name, sizeof( theent.d_name ) ); | 94 | strncpy(theent.d_name, entry.name, sizeof( theent.d_name ) ); |
95 | theent.attribute = entry.attr; | 95 | theent.attribute = entry.attr; |
96 | theent.size = entry.filesize; | 96 | theent.size = entry.filesize; |
97 | theent.startcluster = entry.firstcluster; | ||
97 | 98 | ||
98 | return &theent; | 99 | return &theent; |
99 | } | 100 | } |
diff --git a/firmware/common/dir.h b/firmware/common/dir.h index e03d50901c..274c0b1ea4 100644 --- a/firmware/common/dir.h +++ b/firmware/common/dir.h | |||
@@ -32,6 +32,7 @@ struct dirent { | |||
32 | unsigned char d_name[256]; | 32 | unsigned char d_name[256]; |
33 | int attribute; | 33 | int attribute; |
34 | int size; | 34 | int size; |
35 | int startcluster; | ||
35 | }; | 36 | }; |
36 | #endif | 37 | #endif |
37 | 38 | ||
diff --git a/firmware/common/file.c b/firmware/common/file.c new file mode 100644 index 0000000000..86e1099918 --- /dev/null +++ b/firmware/common/file.c | |||
@@ -0,0 +1,170 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2002 by Björn Stenberg | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | #include <string.h> | ||
20 | #include "file.h" | ||
21 | #include "fat.h" | ||
22 | #include "types.h" | ||
23 | #include "dir.h" | ||
24 | #include "debug.h" | ||
25 | |||
26 | #define MAX_OPEN_FILES 4 | ||
27 | |||
28 | struct filedesc { | ||
29 | unsigned char sector[SECTOR_SIZE]; | ||
30 | int offset; | ||
31 | struct fat_file fatfile; | ||
32 | bool busy; | ||
33 | }; | ||
34 | |||
35 | static struct filedesc openfiles[MAX_OPEN_FILES]; | ||
36 | |||
37 | int open(char* pathname, int flags) | ||
38 | { | ||
39 | DIR* dir; | ||
40 | struct dirent* entry; | ||
41 | int fd; | ||
42 | char* name; | ||
43 | int namelen; | ||
44 | |||
45 | if ( pathname[0] != '/' ) { | ||
46 | DEBUGF("'%s' is not an absolute path.\n",pathname); | ||
47 | DEBUGF("Only absolute pathnames supported at the moment\n"); | ||
48 | return -1; | ||
49 | } | ||
50 | |||
51 | /* find a free file descriptor */ | ||
52 | for ( fd=0; fd<MAX_OPEN_FILES; fd++ ) | ||
53 | if ( !openfiles[fd].busy ) | ||
54 | break; | ||
55 | |||
56 | if ( fd == MAX_OPEN_FILES ) { | ||
57 | DEBUGF("Too many files open\n"); | ||
58 | return -1; | ||
59 | } | ||
60 | |||
61 | /* locate filename */ | ||
62 | name=strrchr(pathname+1,'/'); | ||
63 | if ( name ) { | ||
64 | *name = 0; | ||
65 | dir = opendir(pathname); | ||
66 | *name = '/'; | ||
67 | name++; | ||
68 | } | ||
69 | else { | ||
70 | dir = opendir("/"); | ||
71 | name = pathname+1; | ||
72 | } | ||
73 | if (!dir) { | ||
74 | DEBUGF("Failed opening dir\n"); | ||
75 | return -1; | ||
76 | } | ||
77 | |||
78 | /* scan dir for name */ | ||
79 | namelen = strlen(name); | ||
80 | while ((entry = readdir(dir))) { | ||
81 | if ( !strncmp(name, entry->d_name, namelen) ) { | ||
82 | fat_open(entry->startcluster, &(openfiles[fd].fatfile)); | ||
83 | break; | ||
84 | } | ||
85 | else { | ||
86 | DEBUGF("entry: %s\n",entry->d_name); | ||
87 | } | ||
88 | } | ||
89 | closedir(dir); | ||
90 | if ( !entry ) { | ||
91 | DEBUGF("Couldn't find %s in %s\n",name,pathname); | ||
92 | /* fixme: we need to use proper error codes */ | ||
93 | return -1; | ||
94 | } | ||
95 | |||
96 | openfiles[fd].offset = 0; | ||
97 | openfiles[fd].busy = TRUE; | ||
98 | return fd; | ||
99 | } | ||
100 | |||
101 | int close(int fd) | ||
102 | { | ||
103 | openfiles[fd].busy = FALSE; | ||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | int read(int fd, void* buf, int count) | ||
108 | { | ||
109 | int sectors; | ||
110 | int nread=0; | ||
111 | |||
112 | /* are we in the middle of a cached sector? */ | ||
113 | if ( openfiles[fd].offset ) { | ||
114 | if ( count > (SECTOR_SIZE - openfiles[fd].offset) ) { | ||
115 | memcpy( buf, openfiles[fd].sector, | ||
116 | SECTOR_SIZE - openfiles[fd].offset ); | ||
117 | openfiles[fd].offset = 0; | ||
118 | nread = SECTOR_SIZE - openfiles[fd].offset; | ||
119 | count -= nread; | ||
120 | } | ||
121 | else { | ||
122 | memcpy( buf, openfiles[fd].sector, count ); | ||
123 | openfiles[fd].offset += count; | ||
124 | nread = count; | ||
125 | count = 0; | ||
126 | } | ||
127 | } | ||
128 | |||
129 | /* read whole sectors right into the supplied buffer */ | ||
130 | sectors = count / SECTOR_SIZE; | ||
131 | if ( sectors ) { | ||
132 | if ( fat_read(&(openfiles[fd].fatfile), sectors, buf+nread ) < 0 ) { | ||
133 | DEBUGF("Failed reading %d sectors\n",sectors); | ||
134 | return -1; | ||
135 | } | ||
136 | nread += sectors * SECTOR_SIZE; | ||
137 | count -= sectors * SECTOR_SIZE; | ||
138 | openfiles[fd].offset = 0; | ||
139 | } | ||
140 | |||
141 | /* trailing odd bytes? */ | ||
142 | if ( count ) { | ||
143 | /* do we already have the sector cached? */ | ||
144 | if ( count < (SECTOR_SIZE - openfiles[fd].offset) ) { | ||
145 | memcpy( buf + nread, openfiles[fd].sector, count ); | ||
146 | openfiles[fd].offset += count; | ||
147 | nread += count; | ||
148 | count = 0; | ||
149 | } | ||
150 | else { | ||
151 | /* cache one sector and copy the trailing bytes */ | ||
152 | if ( fat_read(&(openfiles[fd].fatfile), 1, | ||
153 | &(openfiles[fd].sector)) < 0 ) { | ||
154 | DEBUGF("Failed reading odd sector\n"); | ||
155 | return -1; | ||
156 | } | ||
157 | memcpy( buf + nread, openfiles[fd].sector, count ); | ||
158 | openfiles[fd].offset = nread; | ||
159 | nread += count; | ||
160 | } | ||
161 | } | ||
162 | |||
163 | return nread; | ||
164 | } | ||
165 | |||
166 | /* | ||
167 | * local variables: | ||
168 | * eval: (load-file "../rockbox-mode.el") | ||
169 | * end: | ||
170 | */ | ||
diff --git a/firmware/common/file.h b/firmware/common/file.h index 58fb22d881..9d0d6f0501 100644 --- a/firmware/common/file.h +++ b/firmware/common/file.h | |||
@@ -33,14 +33,15 @@ | |||
33 | #ifndef SIMULATOR | 33 | #ifndef SIMULATOR |
34 | extern int open(char* pathname, int flags); | 34 | extern int open(char* pathname, int flags); |
35 | extern int close(int fd); | 35 | extern int close(int fd); |
36 | |||
37 | extern int read(int fd, void* buf, int count); | 36 | extern int read(int fd, void* buf, int count); |
38 | extern int write(int fd, void* buf, int count); | ||
39 | |||
40 | extern int lseek(int fd, int offset, int whence); | 37 | extern int lseek(int fd, int offset, int whence); |
41 | 38 | ||
39 | #ifdef DISK_WRITE | ||
40 | extern int write(int fd, void* buf, int count); | ||
42 | extern int remove(char* pathname); | 41 | extern int remove(char* pathname); |
43 | extern int rename(char* oldname, char* newname); | 42 | extern int rename(char* oldname, char* newname); |
43 | #endif | ||
44 | |||
44 | #else | 45 | #else |
45 | #ifdef WIN32 | 46 | #ifdef WIN32 |
46 | #include <io.h> | 47 | #include <io.h> |