This source file includes following definitions.
- read_next_entry
- rewind_entry
- CHDKOpenDir
- CHDKCloseDir
- check_fn_char
- read_lfn_entry
- CHDKReadDir
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 #include "stdlib.h"
30
31 #define MIN(a,b) ((a) < (b) ? (a) : (b))
32 #define MAX(a,b) ((a) > (b) ? (a) : (b))
33
34 #define FNMAX 107
35 #define DCSIZE 16384
36
37 typedef struct
38 {
39 int fd;
40 char* dc;
41 int cp;
42 int rc;
43
44 union
45 {
46 char *fe;
47 unsigned char *feu;
48 };
49 int islfn;
50 int lfnpos;
51
52 int mnl;
53
54 char fn[FNMAX+1];
55 } myDIR_s;
56
57 static int read_next_entry(myDIR_s* dir)
58 {
59 int rc = 0;
60 if ( (dir->cp==-1) || (dir->cp>=MIN(DCSIZE, dir->rc)) )
61 {
62 rc = read(dir->fd, dir->dc, DCSIZE);
63 if ( rc < 32 )
64 {
65 return rc;
66 }
67 dir->rc = rc;
68 dir->fe = dir->dc;
69 dir->cp = 32;
70 return 32;
71 }
72 else
73 {
74 int canread = MIN(dir->rc - dir->cp, 32);
75 dir->fe = dir->dc + dir->cp;
76 dir->cp += canread;
77 return canread;
78 }
79 }
80
81 static void rewind_entry(myDIR_s* dir)
82 {
83 dir->cp -= 32;
84 }
85
86 void *CHDKOpenDir(const char* name)
87 {
88 myDIR_s *dir = malloc( sizeof(myDIR_s) );
89 if ( dir )
90 {
91 char *dirc = umalloc(DCSIZE);
92 if ( dirc )
93 {
94 dir->fd = open(name, 0, 0x124);
95 if ( dir->fd != -1 )
96 {
97 dir->fn[0] = 0;
98 dir->dc = dirc;
99 dir->cp = -1;
100
101 dir->mnl = MIN(CAM_MAX_FNAME_LENGTH,CAM_MAX_PATH_LENGTH-strlen(name)-1);
102 return dir;
103 }
104 else
105 {
106 free((void*)dir);
107 ufree((void*)dirc);
108 }
109 }
110 else
111 {
112 free((void*)dir);
113 }
114 }
115 return NULL;
116 }
117
118 int CHDKCloseDir(void *d)
119 {
120 myDIR_s *dir = d;
121
122 {
123 int ret = close(dir->fd);
124 ufree(dir->dc);
125 free(d);
126 return ret;
127 }
128 return -1;
129 }
130
131 const unsigned char lfnchpos[]={30,28,24,22,20,18,16,14,9,7,5,3,1};
132
133 int check_fn_char(int i)
134 {
135 if ( i & 0xffffff80 ) return -1;
136 if (
137 ((i >= '0') && (i <= '9')) ||
138 ((i >= '@') && (i <= 'Z')) ||
139 ((i >= 'a') && (i <= 'z')) ||
140 ((i == '.') || (i == '-') || (i == '_') || (i == '(') || (i == ')') || (i == '$') || (i == '&'))
141 )
142 {
143 return i;
144 }
145 if ( i != 0 ) return -1;
146 return 0;
147 }
148
149 void read_lfn_entry(myDIR_s* dir)
150 {
151 int n;
152 for (n=0; n<13; n++)
153 {
154
155 int uch = *(unsigned char*)(dir->fe+lfnchpos[n])+((*(unsigned char*)(dir->fe+lfnchpos[n]+1))<<8);
156 if ((uch != 0xffff) && (uch != 0))
157 {
158 if ( (check_fn_char(uch) < 0) )
159 {
160 dir->islfn = 0;
161 break;
162 }
163 dir->fn[FNMAX-dir->lfnpos] = (char)uch;
164 dir->lfnpos++;
165 }
166 }
167 }
168
169 int CHDKReadDir(void *d, void* dd)
170 {
171 myDIR_s *dir = d;
172 int rd;
173 int lfnchsum = 0;
174 dir->islfn = 0;
175 dir->lfnpos = 0;
176
177
178 {
179 while (1)
180 {
181 rd=read_next_entry(dir);
182 if ( (rd < 32) )
183 {
184 break;
185 }
186 if ( dir->fe[0] == 0 )
187 {
188 break;
189 }
190 if ( (dir->feu[0] == 0xe5) || ((dir->fe[11]&0xf) == 8) )
191 {
192 dir->islfn = 0;
193 continue;
194 }
195 if ( !dir->islfn && (dir->fe[11] != 0xf) )
196 {
197 int n, m;
198 m = 0;
199 for (n=0; n<8; n++)
200 {
201 if ( (n>0) && (dir->fe[n]==0x20) ) break;
202 dir->fn[m] = dir->fe[n];
203 m++;
204 }
205 if ( (dir->fe[8]!=0x20) )
206 {
207 dir->fn[m] = '.';
208 m++;
209 }
210 for (n=8; n<11; n++)
211 {
212 if ( (dir->fe[n]==0x20) ) break;
213 dir->fn[m] = dir->fe[n];
214 m++;
215 }
216 dir->fn[m] = 0;
217 strcpy(dd, dir->fn);
218 return (int)(dir->fn);
219 }
220 if ( (dir->islfn == 1) && (dir->fe[11] != 0xf) )
221 {
222
223 unsigned char cs = 0;
224 int n;
225 for (n = 0; n < 11; n++)
226 {
227 cs = (((cs & 1) << 7) | ((cs & 0xfe) >> 1)) + dir->feu[n];
228 }
229
230 if ( (cs == lfnchsum) && (dir->lfnpos-1 <= dir->mnl) )
231 {
232
233 strcpy(dd, (dir->fn)+FNMAX-dir->lfnpos+1);
234 return (int)((dir->fn)+FNMAX-dir->lfnpos+1);
235 }
236 else
237 {
238 rewind_entry(dir);
239 dir->islfn = 0;
240 continue;
241 }
242 }
243 else if ( dir->fe[11] == 0xf )
244 {
245 if (dir->islfn)
246 {
247 if (
248 (dir->feu[13] != lfnchsum) ||
249 (dir->fe[0] & 0x40) ||
250 (dir->fe[0] != dir->islfn-1)
251 )
252 {
253 dir->islfn = 0;
254 continue;
255 }
256 dir->islfn = dir->fe[0];
257 read_lfn_entry(dir);
258 if ( dir->lfnpos > 99+1 )
259 {
260 dir->islfn = 0;
261 continue;
262 }
263 }
264 else
265 {
266 if ( (dir->fe[0] & 0x40) && (dir->fe[0]-0x40 <= 8) )
267 {
268 dir->islfn = dir->fe[0] - 0x40;
269 memset(dir->fn, 0, FNMAX+1);
270 dir->lfnpos = 1;
271 read_lfn_entry(dir);
272 lfnchsum = dir->feu[13];
273 }
274 else
275 {
276 continue;
277 }
278 }
279 }
280 else
281 {
282 dir->islfn = 0;
283 }
284 }
285
286 dir->fn[0] = 0;
287 strcpy(dd, dir->fn);
288 }
289 return 0;
290 }