resource_manager.c
Go to the documentation of this file.
1 /**
2  * @file resource_manager.c
3  * @brief Embedded resource management
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24  *
25  * @author Oryx Embedded SARL (www.oryx-embedded.com)
26  * @version 2.4.4
27  **/
28 
29 //Dependencies
30 #include <string.h>
31 #include "os_port.h"
32 #include "cpu_endian.h"
33 #include "resource_manager.h"
34 #include "debug.h"
35 
36 //Resource data
37 extern const uint8_t res[];
38 
39 
40 error_t resGetData(const char_t *path, const uint8_t **data, size_t *length)
41 {
42  bool_t found;
43  bool_t match;
44  uint_t n;
45  uint_t dirLength;
46  ResEntry *resEntry;
47 
48  //Point to the resource header
49  ResHeader *resHeader = (ResHeader *) res;
50 
51  //Make sure the resource data is valid
52  if(letoh32(resHeader->totalSize) < sizeof(ResHeader))
54 
55  //Retrieve the length of the root directory
56  dirLength = letoh32(resHeader->rootEntry.dataLength);
57  //Point to the contents of the root directory
58  resEntry = (ResEntry *) (res + letoh32(resHeader->rootEntry.dataStart));
59 
60  //Parse the entire path
61  for(found = FALSE; !found && path[0] != '\0'; path += n + 1)
62  {
63  //Search for the separator that terminates the current token
64  for(n = 0; path[n] != '\\' && path[n] != '/' && path[n] != '\0'; n++)
65  {
66  }
67 
68  if(n == 0 && path[n] != '\0')
69  {
70  path++;
71 
72  for(n = 0; path[n] != '\\' && path[n] != '/' && path[n] != '\0'; n++)
73  {
74  }
75  }
76 
77  //Loop through the directory
78  for(match = FALSE; !match && dirLength > 0; )
79  {
80  //Check the number of remaining bytes
81  if(dirLength < sizeof(ResEntry))
83  //Make sure the entry is valid
84  if(dirLength < (sizeof(ResEntry) + resEntry->nameLength))
86 
87  //Compare current entry name against the expected one
88  if(resEntry->nameLength == n && !strncasecmp(resEntry->name, path, n))
89  {
90  //Check the type of the entry
91  if(resEntry->type == RES_TYPE_DIR)
92  {
93  //Save the length of the directory
94  dirLength = letoh32(resEntry->dataLength);
95  //Point to the contents of the directory
96  resEntry = (ResEntry *) (res + letoh32(resEntry->dataStart));
97  }
98  else
99  {
100  //A file may only appear at the end of the path
101  if(path[n] != '\0')
102  return ERROR_NOT_FOUND;
103 
104  //The search process is complete
105  found = TRUE;
106  }
107  //The current entry matches the specified path
108  match = TRUE;
109  }
110  else
111  {
112  //Remaining bytes to process
113  dirLength -= sizeof(ResEntry) + resEntry->nameLength;
114 
115  //Point to the next entry
116  resEntry = (ResEntry *) ((uint8_t *) resEntry + sizeof(ResEntry) +
117  resEntry->nameLength);
118  }
119  }
120 
121  //Unable to find the specified file?
122  if(!match)
123  return ERROR_NOT_FOUND;
124  }
125 
126  //Unable to find the specified file?
127  if(!found)
128  return ERROR_NOT_FOUND;
129  //Enforce the entry type
130  if(resEntry->type != RES_TYPE_FILE)
131  return ERROR_NOT_FOUND;
132 
133  //Return the location of the specified resource
134  *data = res + letoh32(resEntry->dataStart);
135  //Return the length of the resource
136  *length = letoh32(resEntry->dataLength);
137 
138  //Successful processing
139  return NO_ERROR;
140 }
141 
142 
143 error_t resSearchFile(const char_t *path, DirEntry *dirEntry)
144 {
145  bool_t found;
146  bool_t match;
147  uint_t n;
148  uint_t length;
149  ResEntry *resEntry;
150 
151  //Point to the resource header
152  ResHeader *resHeader = (ResHeader *) res;
153 
154  //Make sure the resource data is valid
155  if(letoh32(resHeader->totalSize) < sizeof(ResHeader))
156  return ERROR_INVALID_RESOURCE;
157 
158  //Retrieve the length of the root directory
159  length = letoh32(resHeader->rootEntry.dataLength);
160  //Point to the contents of the root directory
161  resEntry = (ResEntry *) (res + letoh32(resHeader->rootEntry.dataStart));
162 
163  //Parse the entire path
164  for(found = FALSE; !found && path[0] != '\0'; path += n + 1)
165  {
166  //Search for the separator that terminates the current token
167  for(n = 0; path[n] != '\\' && path[n] != '/' && path[n] != '\0'; n++)
168  {
169  }
170 
171  if(n == 0 && path[n] != '\0')
172  {
173  path++;
174 
175  for(n = 0; path[n] != '\\' && path[n] != '/' && path[n] != '\0'; n++)
176  {
177  }
178  }
179 
180  //Loop through the directory
181  for(match = FALSE; !match && length > 0; )
182  {
183  //Check the number of remaining bytes
184  if(length < sizeof(ResEntry))
185  return ERROR_INVALID_RESOURCE;
186  //Make sure the entry is valid
187  if(length < (sizeof(ResEntry) + resEntry->nameLength))
188  return ERROR_INVALID_RESOURCE;
189 
190  //Compare current entry name against the expected one
191  if(resEntry->nameLength == n && !strncasecmp(resEntry->name, path, n))
192  {
193  //Check the type of the entry
194  if(resEntry->type == RES_TYPE_DIR)
195  {
196  //Save the length of the directory
197  length = letoh32(resEntry->dataLength);
198  //Point to the contents of the directory
199  resEntry = (ResEntry *) (res + letoh32(resEntry->dataStart));
200  }
201  else
202  {
203  //A file may only appear at the end of the path
204  if(path[n] != '\0')
205  return ERROR_INVALID_PATH;
206 
207  //The search process is complete
208  found = TRUE;
209  }
210  //The current entry matches the specified path
211  match = TRUE;
212  }
213  else
214  {
215  //Remaining bytes to process
216  length -= sizeof(ResEntry) + resEntry->nameLength;
217 
218  //Point to the next entry
219  resEntry = (ResEntry *) ((uint8_t *) resEntry + sizeof(ResEntry) +
220  resEntry->nameLength);
221  }
222  }
223 
224  //Unable to find the specified file?
225  if(!match)
226  return ERROR_NOT_FOUND;
227  }
228 
229  //Unable to find the specified file?
230  if(!found)
231  return ERROR_NOT_FOUND;
232 
233  //Return information about the file
234  dirEntry->type = resEntry->type;
235  dirEntry->volume = 0;
236  dirEntry->dataStart = letoh32(resEntry->dataStart);
237  dirEntry->dataLength = letoh32(resEntry->dataLength);
238  dirEntry->nameLength = 0; //resEntry->nameLength;
239  //Copy the filename
240  //osStrncpy(dirEntry->name, resEntry->name, dirEntry->nameLength);
241  //Properly terminate the filename
242  //dirEntry->name[dirEntry->nameLength] = '\0';
243 
244  //Successful processing
245  return NO_ERROR;
246 }
247 
248 #if 0
249 
250 error_t resOpenFile(FsFile *file, const DirEntry *dirEntry, uint_t mode)
251 {
252  file->mode = mode;
253  file->offset = 0;
254  file->start = dirEntry->dataStart;
255  file->size = dirEntry->dataLength;
256 
257  return NO_ERROR;
258 }
259 
260 
261 error_t resSeekFile(FsFile *file, uint32_t *position)
262 {
263  return ERROR_NOT_IMPLEMENTED;
264 }
265 
266 
267 uint_t resReadFile(FsFile *file, void *data, size_t length)
268 {
269  length = MIN(length, file->size - file->offset);
270  osMemcpy(data, res + file->start + file->offset, length);
271  file->offset += length;
272  return length;
273 }
274 
275 FILE *fopen(const char_t *filename, const char_t *mode)
276 {
277  error_t error;
278  DirEntry dirEntry;
279  FsFile *file;
280 
281  error = resSearchFile(filename, &dirEntry);
282  if(error)
283  return NULL;
284 
285  file = osAllocMem(sizeof(FsFile));
286  if(!file)
287  return NULL;
288 
289  error = resOpenFile(file, &dirEntry, MODE_BINARY);
290  if(error)
291  {
292  osFreeMem(file);
293  return NULL;
294  }
295 
296  return (FILE *) file;
297 }
298 
299 
300 size_t fread(void *ptr, size_t size, size_t count, FILE *stream)
301 {
302  uint_t n;
303 
304  n = resReadFile((FsFile *) stream, ptr, size * count);
305 
306  return n / size;
307 }
308 
309 
310 int_t fclose(FILE *stream)
311 {
312  osFreeMem(stream);
313  //The stream is successfully closed
314  return 0;
315 }
316 
317 
318 uint_t fileGetSize(FILE *stream)
319 {
320  uint_t n;
321  n = ((FsFile *) stream)->size;
322  return n;
323 }
324 
325 #endif
@ ERROR_INVALID_RESOURCE
Definition: error.h:145
int bool_t
Definition: compiler_port.h:53
@ ERROR_NOT_FOUND
Definition: error.h:147
ResEntry
@ RES_TYPE_FILE
@ RES_TYPE_DIR
signed int int_t
Definition: compiler_port.h:49
@ ERROR_NOT_IMPLEMENTED
Definition: error.h:66
#define TRUE
Definition: os_port.h:50
uint8_t data[]
Definition: ethernet.h:222
#define strncasecmp
uint_t volume
const uint8_t res[]
uint8_t nameLength
#define letoh32(value)
Definition: cpu_endian.h:438
__weak_func void * osAllocMem(size_t size)
Allocate a memory block.
#define FALSE
Definition: os_port.h:46
uint_t type
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
error_t
Error codes.
Definition: error.h:43
__weak_func void osFreeMem(void *p)
Release a previously allocated memory block.
ResHeader
char_t filename[]
Definition: tftp_common.h:93
error_t resSearchFile(const char_t *path, DirEntry *dirEntry)
uint8_t length
Definition: tcp.h:368
uint32_t dataStart
error_t resGetData(const char_t *path, const uint8_t **data, size_t *length)
#define MIN(a, b)
Definition: os_port.h:63
Byte order conversion.
@ ERROR_INVALID_PATH
Definition: error.h:146
char char_t
Definition: compiler_port.h:48
uint8_t n
uint8_t file[128]
Definition: dhcp_common.h:223
uint32_t dataLength
Embedded resource management.
unsigned int uint_t
Definition: compiler_port.h:50
RTOS abstraction layer.
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
void FsFile
File descriptor.
Definition: fs_port_fatfs.h:60