CHDK_DE Vorschauversion  Trunk Rev. 5234
 Alle Datenstrukturen Dateien Funktionen Variablen Typdefinitionen Aufzählungen Aufzählungswerte Makrodefinitionen
chdk-dir.c-Dateireferenz
#include "stdlib.h"
+ Include-Abhängigkeitsdiagramm für chdk-dir.c:

gehe zum Quellcode dieser Datei

Datenstrukturen

struct  myDIR_s
 

Makrodefinitionen

#define MIN(a, b)   ((a) < (b) ? (a) : (b))
 
#define MAX(a, b)   ((a) > (b) ? (a) : (b))
 
#define FNMAX   107
 
#define DCSIZE   16384
 

Funktionen

static int read_next_entry (myDIR_s *dir)
 
static void rewind_entry (myDIR_s *dir)
 
void * CHDKOpenDir (const char *name)
 
int CHDKCloseDir (void *d)
 
int check_fn_char (int i)
 
void read_lfn_entry (myDIR_s *dir)
 
int CHDKReadDir (void *d, void *dd)
 

Variablen

const unsigned char lfnchpos [] ={30,28,24,22,20,18,16,14,9,7,5,3,1}
 

Makro-Dokumentation

#define DCSIZE   16384

Definiert in Zeile 35 der Datei chdk-dir.c.

#define FNMAX   107

Definiert in Zeile 34 der Datei chdk-dir.c.

#define MAX (   a,
 
)    ((a) > (b) ? (a) : (b))

Definiert in Zeile 32 der Datei chdk-dir.c.

#define MIN (   a,
 
)    ((a) < (b) ? (a) : (b))

Definiert in Zeile 31 der Datei chdk-dir.c.

Dokumentation der Funktionen

int CHDKCloseDir ( void *  d)

Definiert in Zeile 118 der Datei chdk-dir.c.

119 {
120  myDIR_s *dir = d;
121  // if ( d ) // commented out, the wrapper already checks this
122  {
123  int ret = close(dir->fd);
124  ufree(dir->dc);
125  free(d);
126  return ret;
127  }
128  return -1;
129 }
void* CHDKOpenDir ( const char *  name)

Definiert in Zeile 86 der Datei chdk-dir.c.

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  // determine name length limit ('-1' is due to the extra '/' in a full filename)
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; // failure
116 }
int CHDKReadDir ( void *  d,
void *  dd 
)

Definiert in Zeile 169 der Datei chdk-dir.c.

170 {
171  myDIR_s *dir = d;
172  int rd;
173  int lfnchsum = 0; // lfn checksum (only zeroed here to calm down the compiler)
174  dir->islfn = 0; // long file name is being read (state)
175  dir->lfnpos = 0; // position in the long output string (only zeroed here to calm down the compiler)
176 
177  //if ( (int)d && (int)dd ) // commented out, the wrapper already checks this
178  {
179  while (1)
180  {
181  rd=read_next_entry(dir);
182  if ( (rd < 32) ) // either error or short read, return with null string
183  {
184  break;
185  }
186  if ( dir->fe[0] == 0 ) // last entry, return with null string
187  {
188  break;
189  }
190  if ( (dir->feu[0] == 0xe5) || ((dir->fe[11]&0xf) == 8) ) // erased entry or label, makes LFN invalid -> skip entry
191  {
192  dir->islfn = 0;
193  continue;
194  }
195  if ( !dir->islfn && (dir->fe[11] != 0xf) ) // no LFN in progress, not LFN entry -> read short name, return
196  {
197  int n, m;
198  m = 0; // position in output
199  for (n=0; n<8; n++) // name
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) ) // add dot only when there's extension
206  {
207  dir->fn[m] = '.';
208  m++;
209  }
210  for (n=8; n<11; n++) // extension
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) ) // lfn entries over, this must be the short filename entry
221  {
222  // compute checksum
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  // checksum computed
230  if ( (cs == lfnchsum) && (dir->lfnpos-1 <= dir->mnl) )
231  {
232  // lfn is valid, not too long, and belongs to this short name -> return
233  strcpy(dd, (dir->fn)+FNMAX-dir->lfnpos+1);
234  return (int)((dir->fn)+FNMAX-dir->lfnpos+1);
235  }
236  else // invalid checksum or name too long, try re-interpreting entry
237  {
238  rewind_entry(dir);
239  dir->islfn = 0;
240  continue;
241  }
242  }
243  else if ( dir->fe[11] == 0xf ) // lfn entry, process or skip
244  {
245  if (dir->islfn) // already in an lfn block
246  {
247  if ( // check for anomalies:
248  (dir->feu[13] != lfnchsum) || // checksum doesn't match
249  (dir->fe[0] & 0x40) || // first entry of an lfn block
250  (dir->fe[0] != dir->islfn-1) // out of order entry
251  )
252  {
253  dir->islfn = 0;
254  continue;
255  }
256  dir->islfn = dir->fe[0]; // number of lfn entries left + 1
257  read_lfn_entry(dir);
258  if ( dir->lfnpos > 99+1 ) // CHDK limit (100 chars) hit, skip lfn
259  {
260  dir->islfn = 0;
261  continue;
262  }
263  }
264  else // lfn block start
265  {
266  if ( (dir->fe[0] & 0x40) && (dir->fe[0]-0x40 <= 8) ) // start must be valid and name not too long
267  {
268  dir->islfn = dir->fe[0] - 0x40; // number of lfn entries left + 1
269  memset(dir->fn, 0, FNMAX+1);
270  dir->lfnpos = 1; // name will be filled backwards, the last char of the buffer will remain 0 for safety
271  read_lfn_entry(dir);
272  lfnchsum = dir->feu[13];
273  }
274  else // invalid or too long, skip
275  {
276  continue;
277  }
278  }
279  }
280  else // lfn invalid, skip
281  {
282  dir->islfn = 0;
283  }
284  }
285 // problem or end-of-directory
286  dir->fn[0] = 0;
287  strcpy(dd, dir->fn);
288  }
289  return 0;
290 }
int check_fn_char ( int  i)

Definiert in Zeile 133 der Datei chdk-dir.c.

134 {
135  if ( i & 0xffffff80 ) return -1;
136  if (
137  ((i >= '0') && (i <= '9')) ||
138  ((i >= '@'/*'A'*/) && (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 }
void read_lfn_entry ( myDIR_s dir)

Definiert in Zeile 149 der Datei chdk-dir.c.

150 {
151  int n;
152  for (n=0; n<13; n++)
153  {
154  // read unicode char, reading as halfword is not working on armv5 due to alignment
155  int uch = *(unsigned char*)(dir->fe+lfnchpos[n])+((*(unsigned char*)(dir->fe+lfnchpos[n]+1))<<8);
156  if ((uch != 0xffff) && (uch != 0)) // unused space is filled with '0xffff' chars and zero or one '0x0' char
157  {
158  if ( (check_fn_char(uch) < 0) ) // disable lfn if any chars are outside 7bit ascii
159  {
160  dir->islfn = 0;
161  break;
162  }
163  dir->fn[FNMAX-dir->lfnpos] = (char)uch;
164  dir->lfnpos++;
165  }
166  }
167 }
static int read_next_entry ( myDIR_s dir)
static

Definiert in Zeile 57 der Datei chdk-dir.c.

58 {
59  int rc = 0;
60  if ( (dir->cp==-1) || (dir->cp>=MIN(DCSIZE, dir->rc)) ) // cache empty or fully read out
61  {
62  rc = read(dir->fd, dir->dc, DCSIZE);
63  if ( rc < 32 ) // short read or error
64  {
65  return rc;
66  }
67  dir->rc = rc;
68  dir->fe = dir->dc;
69  dir->cp = 32;
70  return 32;
71  }
72  else // read from cache
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 }
static void rewind_entry ( myDIR_s dir)
static

Definiert in Zeile 81 der Datei chdk-dir.c.

82 {
83  dir->cp -= 32;
84 }

Variablen-Dokumentation

const unsigned char lfnchpos[] ={30,28,24,22,20,18,16,14,9,7,5,3,1}

Definiert in Zeile 131 der Datei chdk-dir.c.