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-2022 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.2.0
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  if(n == 0 && path[n] != '\0')
170  {
171  path++;
172  for(n = 0; path[n] != '\\' && path[n] != '/' && path[n] != '\0'; n++);
173  }
174 
175  //Loop through the directory
176  for(match = FALSE; !match && length > 0; )
177  {
178  //Check the number of remaining bytes
179  if(length < sizeof(ResEntry))
180  return ERROR_INVALID_RESOURCE;
181  //Make sure the entry is valid
182  if(length < (sizeof(ResEntry) + resEntry->nameLength))
183  return ERROR_INVALID_RESOURCE;
184 
185  //Compare current entry name against the expected one
186  if(resEntry->nameLength == n && !strncasecmp(resEntry->name, path, n))
187  {
188  //Check the type of the entry
189  if(resEntry->type == RES_TYPE_DIR)
190  {
191  //Save the length of the directory
192  length = letoh32(resEntry->dataLength);
193  //Point to the contents of the directory
194  resEntry = (ResEntry *) (res + letoh32(resEntry->dataStart));
195  }
196  else
197  {
198  //A file may only appear at the end of the path
199  if(path[n] != '\0')
200  return ERROR_INVALID_PATH;
201 
202  //The search process is complete
203  found = TRUE;
204  }
205  //The current entry matches the specified path
206  match = TRUE;
207  }
208  else
209  {
210  //Remaining bytes to process
211  length -= sizeof(ResEntry) + resEntry->nameLength;
212 
213  //Point to the next entry
214  resEntry = (ResEntry *) ((uint8_t *) resEntry + sizeof(ResEntry) +
215  resEntry->nameLength);
216  }
217  }
218 
219  //Unable to find the specified file?
220  if(!match)
221  return ERROR_NOT_FOUND;
222  }
223 
224  //Unable to find the specified file?
225  if(!found)
226  return ERROR_NOT_FOUND;
227 
228  //Return information about the file
229  dirEntry->type = resEntry->type;
230  dirEntry->volume = 0;
231  dirEntry->dataStart = letoh32(resEntry->dataStart);
232  dirEntry->dataLength = letoh32(resEntry->dataLength);
233  dirEntry->nameLength = 0; //resEntry->nameLength;
234  //Copy the filename
235  //osStrncpy(dirEntry->name, resEntry->name, dirEntry->nameLength);
236  //Properly terminate the filename
237  //dirEntry->name[dirEntry->nameLength] = '\0';
238 
239  //Successful processing
240  return NO_ERROR;
241 }
242 
243 #if 0
244 
245 error_t resOpenFile(FsFile *file, const DirEntry *dirEntry, uint_t mode)
246 {
247  file->mode = mode;
248  file->offset = 0;
249  file->start = dirEntry->dataStart;
250  file->size = dirEntry->dataLength;
251 
252  return NO_ERROR;
253 }
254 
255 
256 error_t resSeekFile(FsFile *file, uint32_t *position)
257 {
258  return ERROR_NOT_IMPLEMENTED;
259 }
260 
261 
262 uint_t resReadFile(FsFile *file, void *data, size_t length)
263 {
264  length = MIN(length, file->size - file->offset);
265  osMemcpy(data, res + file->start + file->offset, length);
266  file->offset += length;
267  return length;
268 }
269 
270 FILE *fopen(const char_t *filename, const char_t *mode)
271 {
272  error_t error;
273  DirEntry dirEntry;
274  FsFile *file;
275 
276  error = resSearchFile(filename, &dirEntry);
277  if(error)
278  return NULL;
279 
280  file = osAllocMem(sizeof(FsFile));
281  if(!file)
282  return NULL;
283 
284  error = resOpenFile(file, &dirEntry, MODE_BINARY);
285  if(error)
286  {
287  osFreeMem(file);
288  return NULL;
289  }
290 
291  return (FILE *) file;
292 }
293 
294 
295 size_t fread(void *ptr, size_t size, size_t count, FILE *stream)
296 {
297  uint_t n;
298 
299  n = resReadFile((FsFile *) stream, ptr, size * count);
300 
301  return n / size;
302 }
303 
304 
305 int_t fclose(FILE * stream)
306 {
307  osFreeMem(stream);
308  //The stream is successfully closed
309  return 0;
310 }
311 
312 
313 uint_t fileGetSize(FILE *stream)
314 {
315  uint_t n;
316  n = ((FsFile *) stream)->size;
317  return n;
318 }
319 
320 #endif
@ ERROR_INVALID_RESOURCE
Definition: error.h:144
uint8_t length
Definition: coap_common.h:193
int bool_t
Definition: compiler_port.h:48
@ ERROR_NOT_FOUND
Definition: error.h:146
@ RES_TYPE_FILE
@ RES_TYPE_DIR
uint8_t data[]
Definition: ethernet.h:220
signed int int_t
Definition: compiler_port.h:44
@ ERROR_NOT_IMPLEMENTED
Definition: error.h:66
#define TRUE
Definition: os_port.h:50
#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.
__start_packed struct @2 ResHeader
Resource header.
#define FALSE
Definition: os_port.h:46
uint_t type
#define osMemcpy(dest, src, length)
Definition: os_port.h:137
char_t filename[]
Definition: tftp_common.h:91
error_t
Error codes.
Definition: error.h:43
__weak_func void osFreeMem(void *p)
Release a previously allocated memory block.
__start_packed struct @0 ResEntry
Resource entry.
error_t resSearchFile(const char_t *path, DirEntry *dirEntry)
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:62
Byte order conversion.
@ ERROR_INVALID_PATH
Definition: error.h:145
char char_t
Definition: compiler_port.h:43
uint8_t n
uint8_t file[128]
Definition: dhcp_common.h:221
uint32_t dataLength
uint8_t mode
Definition: ntp_common.h:149
Embedded resource management.
unsigned int uint_t
Definition: compiler_port.h:45
RTOS abstraction layer.
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
void FsFile
File descriptor.
Definition: fs_port_fatfs.h:60