Webserver+3d print
Embed:
(wiki syntax)
Show/hide line numbers
resource_manager.c
Go to the documentation of this file.
00001 /** 00002 * @file resource_manager.c 00003 * @brief Embedded resource management 00004 * 00005 * @section License 00006 * 00007 * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved. 00008 * 00009 * This program is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU General Public License 00011 * as published by the Free Software Foundation; either version 2 00012 * of the License, or (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License 00020 * along with this program; if not, write to the Free Software Foundation, 00021 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00022 * 00023 * @author Oryx Embedded SARL (www.oryx-embedded.com) 00024 * @version 1.7.6 00025 **/ 00026 00027 //Dependencies 00028 #include <string.h> 00029 #include "os_port.h" 00030 #include "resource_manager.h" 00031 #include "debug.h" 00032 00033 //Resource data 00034 extern uint8_t res[]; 00035 00036 00037 error_t resGetData(const char_t *path, uint8_t **data, size_t *length) 00038 { 00039 bool_t found; 00040 bool_t match; 00041 uint_t n; 00042 uint_t dirLength; 00043 ResEntry *resEntry; 00044 00045 //Point to the resource header 00046 ResHeader *resHeader = (ResHeader *) res; 00047 00048 //Make sure the resource data is valid 00049 if(resHeader->totalSize < sizeof(ResHeader)) 00050 return ERROR_INVALID_RESOURCE; 00051 00052 //Retrieve the length of the root directory 00053 dirLength = resHeader->rootEntry.dataLength; 00054 //Point to the contents of the root directory 00055 resEntry = (ResEntry *) (res + resHeader->rootEntry.dataStart); 00056 00057 //Parse the entire path 00058 for(found = FALSE; !found && path[0] != '\0'; path += n + 1) 00059 { 00060 //Search for the separator that terminates the current token 00061 for(n = 0; path[n] != '\\' && path[n] != '/' && path[n] != '\0'; n++); 00062 00063 if(n == 0 && path[n] != '\0') 00064 { 00065 path++; 00066 for(n = 0; path[n] != '\\' && path[n] != '/' && path[n] != '\0'; n++); 00067 } 00068 00069 //Loop through the directory 00070 for(match = FALSE; !match && dirLength > 0; ) 00071 { 00072 //Check the number of remaining bytes 00073 if(dirLength < sizeof(ResEntry)) 00074 return ERROR_INVALID_RESOURCE; 00075 //Make sure the entry is valid 00076 if(dirLength < (sizeof(ResEntry) + resEntry->nameLength)) 00077 return ERROR_INVALID_RESOURCE; 00078 00079 //Compare current entry name against the expected one 00080 if(resEntry->nameLength == n && !strncasecmp(resEntry->name, path, n)) 00081 { 00082 //Check the type of the entry 00083 if(resEntry->type == RES_TYPE_DIR) 00084 { 00085 //Save the length of the directory 00086 dirLength = resEntry->dataLength; 00087 //Point to the contents of the directory 00088 resEntry = (ResEntry *) (res + resEntry->dataStart); 00089 } 00090 else 00091 { 00092 //A file may only appear at the end of the path 00093 if(path[n] != '\0') 00094 return ERROR_NOT_FOUND; 00095 00096 //The search process is complete 00097 found = TRUE; 00098 } 00099 //The current entry matches the specified path 00100 match = TRUE; 00101 } 00102 else 00103 { 00104 //Remaining bytes to process 00105 dirLength -= sizeof(ResEntry) + resEntry->nameLength; 00106 //Point to the next entry 00107 resEntry = (ResEntry *) ((uint8_t *) resEntry + sizeof(ResEntry) + resEntry->nameLength); 00108 } 00109 } 00110 00111 //Unable to find the specified file? 00112 if(!match) 00113 return ERROR_NOT_FOUND; 00114 } 00115 00116 //Unable to find the specified file? 00117 if(!found) 00118 return ERROR_NOT_FOUND; 00119 //Enforce the entry type 00120 if(resEntry->type != RES_TYPE_FILE) 00121 return ERROR_NOT_FOUND; 00122 00123 //Return the location of the specified resource 00124 *data = res + resEntry->dataStart; 00125 //Return the length of the resource 00126 *length = resEntry->dataLength; 00127 00128 //Successful processing 00129 return NO_ERROR; 00130 } 00131 00132 00133 error_t resSearchFile(const char_t *path, DirEntry *dirEntry) 00134 { 00135 bool_t found; 00136 bool_t match; 00137 uint_t n; 00138 uint_t length; 00139 ResEntry *resEntry; 00140 00141 //Point to the resource header 00142 ResHeader *resHeader = (ResHeader *) res; 00143 00144 //Make sure the resource data is valid 00145 if(resHeader->totalSize < sizeof(ResHeader)) 00146 return ERROR_INVALID_RESOURCE; 00147 00148 //Retrieve the length of the root directory 00149 length = resHeader->rootEntry.dataLength; 00150 //Point to the contents of the root directory 00151 resEntry = (ResEntry *) (res + resHeader->rootEntry.dataStart); 00152 00153 //Parse the entire path 00154 for(found = FALSE; !found && path[0] != '\0'; path += n + 1) 00155 { 00156 //Search for the separator that terminates the current token 00157 for(n = 0; path[n] != '\\' && path[n] != '/' && path[n] != '\0'; n++); 00158 00159 if(n == 0 && path[n] != '\0') 00160 { 00161 path++; 00162 for(n = 0; path[n] != '\\' && path[n] != '/' && path[n] != '\0'; n++); 00163 } 00164 00165 //Loop through the directory 00166 for(match = FALSE; !match && length > 0; ) 00167 { 00168 //Check the number of remaining bytes 00169 if(length < sizeof(ResEntry)) 00170 return ERROR_INVALID_RESOURCE; 00171 //Make sure the entry is valid 00172 if(length < (sizeof(ResEntry) + resEntry->nameLength)) 00173 return ERROR_INVALID_RESOURCE; 00174 00175 //Compare current entry name against the expected one 00176 if(resEntry->nameLength == n && !strncasecmp(resEntry->name, path, n)) 00177 { 00178 //Check the type of the entry 00179 if(resEntry->type == RES_TYPE_DIR) 00180 { 00181 //Save the length of the directory 00182 length = resEntry->dataLength; 00183 //Point to the contents of the directory 00184 resEntry = (ResEntry *) (res + resEntry->dataStart); 00185 } 00186 else 00187 { 00188 //A file may only appear at the end of the path 00189 if(path[n] != '\0') 00190 return ERROR_INVALID_PATH; 00191 00192 //The search process is complete 00193 found = TRUE; 00194 } 00195 //The current entry matches the specified path 00196 match = TRUE; 00197 } 00198 else 00199 { 00200 //Remaining bytes to process 00201 length -= sizeof(ResEntry) + resEntry->nameLength; 00202 //Point to the next entry 00203 resEntry = (ResEntry *) ((uint8_t *) resEntry + sizeof(ResEntry) + resEntry->nameLength); 00204 } 00205 } 00206 00207 //Unable to find the specified file? 00208 if(!match) 00209 return ERROR_NOT_FOUND; 00210 } 00211 00212 //Unable to find the specified file? 00213 if(!found) 00214 return ERROR_NOT_FOUND; 00215 00216 //Return information about the file 00217 dirEntry->type = resEntry->type; 00218 dirEntry->volume = 0; 00219 dirEntry->dataStart = resEntry->dataStart; 00220 dirEntry->dataLength = resEntry->dataLength; 00221 dirEntry->nameLength = 0; //resEntry->nameLength; 00222 //Copy the filename 00223 //strncpy(dirEntry->name, resEntry->name, dirEntry->nameLength); 00224 //Properly terminate the filename 00225 //dirEntry->name[dirEntry->nameLength] = '\0'; 00226 00227 //Successful processing 00228 return NO_ERROR; 00229 } 00230 00231 #if 0 00232 00233 error_t resOpenFile(FsFile *file, const DirEntry *dirEntry, uint_t mode) 00234 { 00235 file->mode = mode; 00236 file->offset = 0; 00237 file->start = dirEntry->dataStart; 00238 file->size = dirEntry->dataLength; 00239 00240 return NO_ERROR; 00241 } 00242 00243 00244 error_t resSeekFile(FsFile *file, uint32_t *position) 00245 { 00246 return ERROR_NOT_IMPLEMENTED; 00247 } 00248 00249 00250 uint_t resReadFile(FsFile *file, void *data, size_t length) 00251 { 00252 length = MIN(length, file->size - file->offset); 00253 memcpy(data, res + file->start + file->offset, length); 00254 file->offset += length; 00255 return length; 00256 } 00257 00258 FILE *fopen(const char_t *filename, const char_t *mode) 00259 { 00260 error_t error; 00261 DirEntry dirEntry; 00262 FsFile *file; 00263 00264 error = resSearchFile(filename, &dirEntry); 00265 if(error) 00266 return NULL; 00267 00268 file = osAllocMem(sizeof(FsFile)); 00269 if(!file) 00270 return NULL; 00271 00272 error = resOpenFile(file, &dirEntry, MODE_BINARY); 00273 if(error) 00274 { 00275 osFreeMem(file); 00276 return NULL; 00277 } 00278 00279 return (FILE *) file; 00280 } 00281 00282 00283 size_t fread(void *ptr, size_t size, size_t count, FILE *stream) 00284 { 00285 uint_t n; 00286 00287 n = resReadFile((FsFile *) stream, ptr, size * count); 00288 00289 return n / size; 00290 } 00291 00292 00293 int_t fclose(FILE * stream) 00294 { 00295 osFreeMem(stream); 00296 //The stream is successfully closed 00297 return 0; 00298 } 00299 00300 00301 uint_t fileGetSize(FILE *stream) 00302 { 00303 uint_t n; 00304 n = ((FsFile *) stream)->size; 00305 return n; 00306 } 00307 00308 #endif 00309
Generated on Tue Jul 12 2022 17:10:15 by
