Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: GR-PEACH_Digital_Signage
scan_folder.cpp
00001 /******************************************************************************* 00002 * DISCLAIMER 00003 * This software is supplied by Renesas Electronics Corporation and is only 00004 * intended for use with Renesas products. No other uses are authorized. This 00005 * software is owned by Renesas Electronics Corporation and is protected under 00006 * all applicable laws, including copyright laws. 00007 * THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING 00008 * THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT 00009 * LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE 00010 * AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED. 00011 * TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS 00012 * ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE 00013 * FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR 00014 * ANY REASON RELATED TO THIS SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE 00015 * BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 00016 * Renesas reserves the right, without notice, to make changes to this software 00017 * and to discontinue the availability of this software. By using this software, 00018 * you agree to the additional terms and conditions found by accessing the 00019 * following link: 00020 * http://www.renesas.com/disclaimer* 00021 * Copyright (C) 2015 Renesas Electronics Corporation. All rights reserved. 00022 *******************************************************************************/ 00023 00024 #include "mbed.h" 00025 #include "rtos.h" 00026 #include "FATFileSystem.h" 00027 #include "scan_folder.h" 00028 00029 /*--- Macro definition of folder structure scan. ---*/ 00030 /* The character string to identify root directory. */ 00031 #define STR_ROOT_FOR_F_OPENDIR "" /* to use f_opendir() */ 00032 00033 #define CHR_FULL_STOP '.' /* 0x2E: FULL STOP */ 00034 #define CHR_SOLIDUS '/' /* 0x2F: SOLIDUS */ 00035 #define FOLD_ID_NOT_EXIST (0xFFFFFFFFu) 00036 #define OPEN_MODE_READ_ONLY "r" 00037 00038 /* File path maximum size including the usb mount name size */ 00039 #define FILE_PATH_MAX_SIZE (64u) 00040 00041 #define SCAN_WAIT_TIME_MS (1) 00042 00043 00044 void ScanFolder::init() { 00045 scan_data.total_folder = 0u; 00046 scan_data.total_file = 0u; 00047 } 00048 00049 bool ScanFolder::scan(char_t * p_root_name, const char_t ** pp_extension_tbl) { 00050 bool ret = false; 00051 bool result; 00052 bool chk; 00053 uint32_t i; 00054 item_t *p_item; 00055 FATFS_DIR fdir; 00056 const char_t *p_name; 00057 bool flg_dir; 00058 bool chk_dep; 00059 00060 /* Initializes the scan data. */ 00061 scan_data.total_file = 0u; 00062 scan_data.total_folder = 0u; 00063 00064 /* Registers the identifier of the root directory to use f_opendir(). */ 00065 (void) regist_item(&scan_data.folder_list[0], STR_ROOT_FOR_F_OPENDIR, FOLD_ID_NOT_EXIST); 00066 scan_data.total_folder++; 00067 00068 /* Checks the item in all registered directory. */ 00069 for (i = 0; i < scan_data.total_folder; i++) { 00070 chk_dep = check_folder_depth(i); 00071 result = open_dir(&scan_data.folder_list[i], &fdir); 00072 while (result != false) { 00073 result = read_dir(&fdir, &p_name, &flg_dir); 00074 if (result != false) { 00075 /* Checks the attribute of this item. */ 00076 if (flg_dir != false) { 00077 /* This item is directory. */ 00078 if ((chk_dep != false) && (scan_data.total_folder < MAX_FOLDER_NUM)) { 00079 p_item = &scan_data.folder_list[scan_data.total_folder]; 00080 chk = regist_item(p_item, p_name, i); 00081 if (chk != false) { 00082 /* Register of directory item was success. */ 00083 scan_data.total_folder++; 00084 } 00085 } 00086 } else { 00087 /* This item is file. */ 00088 chk = check_extension(p_name, pp_extension_tbl); 00089 if ((chk != false) && (scan_data.total_file < MAX_TRACK_NUM)) { 00090 /* This item is requested file. */ 00091 p_item = &scan_data.track_list[scan_data.total_file]; 00092 chk = regist_item(p_item, p_name, i); 00093 if (chk != false) { 00094 /* Register of file item was success. */ 00095 scan_data.total_file++; 00096 } 00097 } 00098 } 00099 Thread::wait(SCAN_WAIT_TIME_MS); 00100 } 00101 } 00102 } 00103 /* Changes the identifier of the root directory to use fopen(). */ 00104 (void) regist_item(&scan_data.folder_list[0], p_root_name, FOLD_ID_NOT_EXIST); 00105 00106 if (scan_data.total_file > 0u) { 00107 ret = true; 00108 } 00109 00110 return ret; 00111 } 00112 00113 FILE * ScanFolder::open(const uint32_t track_id) { 00114 FILE *fp = NULL; 00115 const char_t *p_path; 00116 size_t path_len; 00117 00118 if (track_id < scan_data.total_file) { 00119 p_path = get_full_path(&scan_data.track_list[track_id]); 00120 if (p_path != NULL) { 00121 path_len = strlen(p_path); 00122 /* File path maximum length is limited by the specification of "fopen". */ 00123 if (path_len < FILE_PATH_MAX_SIZE) { 00124 fp = fopen(p_path, OPEN_MODE_READ_ONLY); 00125 } 00126 } 00127 } 00128 return fp; 00129 } 00130 00131 void ScanFolder::close(FILE * const fp) { 00132 if (fp != NULL) { 00133 (void) fclose(fp); 00134 } 00135 } 00136 00137 const char_t * ScanFolder::getFileName(const uint32_t track_id) { 00138 const char_t *p_name = NULL; 00139 00140 if (track_id < scan_data.total_file) { 00141 p_name = &scan_data.track_list[track_id].name[0]; 00142 } 00143 return p_name; 00144 } 00145 00146 uint32_t ScanFolder::getTotalFile() { 00147 uint32_t ret; 00148 00149 ret = scan_data.total_file; 00150 return ret; 00151 } 00152 00153 /** Gets the full path 00154 * 00155 * @param p_item Pointer to the item structure of the folder / track. 00156 * 00157 * @returns 00158 * Pointer to the full path. 00159 */ 00160 const char_t * ScanFolder::get_full_path(const item_t * const p_item) { 00161 const char_t *p_path = NULL; 00162 const item_t *p; 00163 const item_t *item_list[MAX_FOLDER_DEPTH]; 00164 uint32_t i; 00165 uint32_t item_cnt; 00166 uint32_t buf_cnt; 00167 uint32_t len; 00168 bool err; 00169 00170 if (p_item != NULL) { 00171 for (i = 0; i < MAX_FOLDER_DEPTH; i++) { 00172 item_list[i] = NULL; 00173 } 00174 scan_data.work_buf[0] = '\0'; 00175 00176 /* Stores the item name until the root folder. */ 00177 p = p_item; 00178 item_cnt = 0; 00179 while ((item_cnt < MAX_FOLDER_DEPTH) && 00180 (p->parent_number < scan_data.total_folder)) { 00181 item_list[item_cnt] = p; 00182 item_cnt++; 00183 p = &scan_data.folder_list[p->parent_number]; 00184 } 00185 if (p->parent_number == FOLD_ID_NOT_EXIST) { 00186 buf_cnt = strlen(p->name); 00187 (void) strncpy(&scan_data.work_buf[0], p->name, sizeof(scan_data.work_buf)); 00188 err = false; 00189 while ((item_cnt > 0u) && (err != true)) { 00190 item_cnt--; 00191 p = item_list[item_cnt]; 00192 /* Concatenates SOLIDUS character to the "work_buf" variable. */ 00193 if ((buf_cnt + 1u) < sizeof(scan_data.work_buf)) { 00194 scan_data.work_buf[buf_cnt] = CHR_SOLIDUS; 00195 buf_cnt++; 00196 } else { 00197 err = true; 00198 } 00199 /* Concatenates the item name to the "work_buf" variable. */ 00200 if (p != NULL) { 00201 len = strlen(p->name); 00202 if ((buf_cnt + len) < sizeof(scan_data.work_buf)) { 00203 (void) strncpy(&scan_data.work_buf[buf_cnt], p->name, len); 00204 buf_cnt += len; 00205 } else { 00206 err = true; 00207 } 00208 } 00209 } 00210 if (err != true) { 00211 scan_data.work_buf[buf_cnt] = '\0'; 00212 p_path = &scan_data.work_buf[0]; 00213 } 00214 } 00215 } 00216 return p_path; 00217 } 00218 00219 /** Opens the directory 00220 * 00221 * @param p_item Pointer to the item structure of the folder / track. 00222 * @param p_fdir Pointer to the structure to store the directory object. 00223 * 00224 * @returns 00225 * Results of process. true is success. false is failure. 00226 */ 00227 bool ScanFolder::open_dir(const item_t * const p_item, FATFS_DIR * const p_fdir) { 00228 bool ret = false; 00229 const char_t *p_path; 00230 FRESULT ferr; 00231 00232 if ((p_item != NULL) && (p_fdir != NULL)) { 00233 p_path = get_full_path(p_item); 00234 if (p_path != NULL) { 00235 ferr = f_opendir(p_fdir, p_path); 00236 if (ferr == FR_OK) { 00237 ret = true; 00238 } 00239 } 00240 } 00241 return ret; 00242 } 00243 00244 /** Reads the directory 00245 * 00246 * @param p_fdir Pointer to the structure of the directory object. 00247 * @param p_flag_dir Pointer to the variable to store the directory flag. 00248 * 00249 * @returns 00250 * Pointer to the name. 00251 */ 00252 bool ScanFolder::read_dir(FATFS_DIR * const p_fdir, const char_t ** const p_name, bool * const p_flag_dir) { 00253 bool ret = false; 00254 FRESULT ferr; 00255 FILINFO finfo; 00256 00257 if ((p_fdir != NULL) && 00258 (p_name != NULL) && (p_flag_dir != NULL)) { 00259 /* Sets the buffer to store the long file name. */ 00260 finfo.lfname = &scan_data.work_buf[0]; 00261 finfo.lfsize = sizeof(scan_data.work_buf); 00262 ferr = f_readdir(p_fdir, &finfo); 00263 if ((ferr == FR_OK) && ((int32_t)finfo.fname[0] != '\0')) { 00264 if (finfo.lfname != NULL) { 00265 if ((int32_t)finfo.lfname[0] == '\0') { 00266 /* Long file name does not exist. */ 00267 (void) strncpy(finfo.lfname, finfo.fname, finfo.lfsize); 00268 } 00269 /* Adds the NULL terminal character. */ 00270 /* This is fail-safe processing. */ 00271 finfo.lfname[finfo.lfsize - 1u] = '\0'; 00272 00273 ret = true; 00274 *p_name = finfo.lfname; 00275 if ((finfo.fattrib & AM_DIR) != 0) { 00276 /* This item is directory. */ 00277 *p_flag_dir = true; 00278 } else { 00279 /* This item is file. */ 00280 *p_flag_dir = false; 00281 } 00282 } 00283 } 00284 } 00285 return ret; 00286 } 00287 00288 /** Registers the item of the folder / track 00289 * 00290 * @param p_item Pointer to the structure to store the item of the folder / track. 00291 * @param p_name Pointer to the name of the item. 00292 * @param parent Number of the parent folder of the item. 00293 * 00294 * @returns 00295 * Results of process. true is success. false is failure. 00296 */ 00297 bool ScanFolder::regist_item(item_t * const p_item, const char_t * const p_name, const uint32_t parent) { 00298 bool ret = false; 00299 uint32_t len; 00300 00301 if ((p_item != NULL) && (p_name != NULL)) { 00302 len = strlen(p_name); 00303 if ((len + 1u) < sizeof(p_item->name)) { 00304 (void) strncpy(p_item->name, p_name, sizeof(p_item->name)); 00305 p_item->name[sizeof(p_item->name) - 1u] = '\0'; 00306 p_item->parent_number = parent; 00307 ret = true; 00308 } 00309 } 00310 return ret; 00311 } 00312 00313 /** Checks the extension of the track name 00314 * 00315 * @param p_name Pointer to the name of the track. 00316 * 00317 * @returns 00318 * Results of the checking. true is requested file. false is other file. 00319 */ 00320 bool ScanFolder::check_extension(const char_t * const p_name, const char_t ** pp_extension_tbl) { 00321 bool ret = false; 00322 const char_t *p; 00323 size_t extension_len; 00324 const char_t * p_extension; 00325 00326 if (p_name != NULL) { 00327 p = strrchr(p_name, CHR_FULL_STOP); 00328 if (p != NULL) { 00329 while (1) { 00330 p_extension = *(pp_extension_tbl++); 00331 if (p_extension != NULL) { 00332 extension_len = strlen(p_extension); 00333 if (strncasecmp(p, p_extension, extension_len) == 0) { 00334 ret = true; 00335 break; 00336 } 00337 } else { 00338 break; 00339 } 00340 } 00341 } 00342 } 00343 return ret; 00344 } 00345 00346 /** Checks the folder depth in the scan range 00347 * 00348 * @param folder_id Folder ID [0 - (total folder - 1)] 00349 * 00350 * @returns 00351 * Results of the checking. true is the scan range. false is out of a scan range. 00352 */ 00353 bool ScanFolder::check_folder_depth(const uint32_t folder_id) { 00354 bool ret = false; 00355 uint32_t depth; 00356 uint32_t parent_id; 00357 00358 /* Counts the folder depth. */ 00359 parent_id = folder_id; 00360 depth = 0u; 00361 while ((depth < MAX_FOLDER_DEPTH) && 00362 (parent_id < scan_data.total_folder)) { 00363 depth++; 00364 parent_id = scan_data.folder_list[parent_id].parent_number; 00365 } 00366 if (parent_id == FOLD_ID_NOT_EXIST) { 00367 /* Found the root folder. */ 00368 if (depth < MAX_FOLDER_DEPTH) { 00369 ret = true; 00370 } 00371 } 00372 return ret; 00373 }
Generated on Sun Jul 17 2022 09:46:02 by
1.7.2