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: TYBLE16_simple_data_logger TYBLE16_MP3_Air
lfs_emubd.c
00001 /* 00002 * Block device emulated on standard files 00003 * 00004 * Copyright (c) 2017, Arm Limited. All rights reserved. 00005 * SPDX-License-Identifier: BSD-3-Clause 00006 */ 00007 #include "emubd/lfs_emubd.h" 00008 00009 #include <errno.h> 00010 #include <string.h> 00011 #include <stdlib.h> 00012 #include <stdio.h> 00013 #include <limits.h> 00014 #include <dirent.h> 00015 #include <sys/stat.h> 00016 #include <unistd.h> 00017 #include <assert.h> 00018 #include <stdbool.h> 00019 #include <inttypes.h> 00020 00021 00022 // Block device emulated on existing filesystem 00023 int lfs_emubd_create(const struct lfs_config *cfg, const char *path) { 00024 lfs_emubd_t *emu = cfg->context; 00025 emu->cfg.read_size = cfg->read_size; 00026 emu->cfg.prog_size = cfg->prog_size; 00027 emu->cfg.block_size = cfg->block_size; 00028 emu->cfg.block_count = cfg->block_count; 00029 00030 // Allocate buffer for creating children files 00031 size_t pathlen = strlen(path); 00032 emu->path = malloc(pathlen + 1 + LFS_NAME_MAX + 1); 00033 if (!emu->path) { 00034 return -ENOMEM; 00035 } 00036 00037 strcpy(emu->path, path); 00038 emu->path[pathlen] = '/'; 00039 emu->child = &emu->path[pathlen+1]; 00040 memset(emu->child, '\0', LFS_NAME_MAX+1); 00041 00042 // Create directory if it doesn't exist 00043 int err = mkdir(path, 0777); 00044 if (err && errno != EEXIST) { 00045 return -errno; 00046 } 00047 00048 // Load stats to continue incrementing 00049 snprintf(emu->child, LFS_NAME_MAX, "stats"); 00050 00051 FILE *f = fopen(emu->path, "r"); 00052 if (!f && errno != ENOENT) { 00053 return -errno; 00054 } 00055 00056 if (errno == ENOENT) { 00057 memset(&emu->stats, 0x0, sizeof(emu->stats)); 00058 } else { 00059 size_t res = fread(&emu->stats, sizeof(emu->stats), 1, f); 00060 if (res < 1) { 00061 return -errno; 00062 } 00063 00064 err = fclose(f); 00065 if (err) { 00066 return -errno; 00067 } 00068 } 00069 00070 return 0; 00071 } 00072 00073 void lfs_emubd_destroy(const struct lfs_config *cfg) { 00074 lfs_emubd_sync(cfg); 00075 00076 lfs_emubd_t *emu = cfg->context; 00077 free(emu->path); 00078 } 00079 00080 int lfs_emubd_read(const struct lfs_config *cfg, lfs_block_t block, 00081 lfs_off_t off, void *buffer, lfs_size_t size) { 00082 lfs_emubd_t *emu = cfg->context; 00083 uint8_t *data = buffer; 00084 00085 // Check if read is valid 00086 assert(off % cfg->read_size == 0); 00087 assert(size % cfg->read_size == 0); 00088 assert(block < cfg->block_count); 00089 00090 // Zero out buffer for debugging 00091 memset(data, 0, size); 00092 00093 // Read data 00094 snprintf(emu->child, LFS_NAME_MAX, "%" PRIx32, block); 00095 00096 FILE *f = fopen(emu->path, "rb"); 00097 if (!f && errno != ENOENT) { 00098 return -errno; 00099 } 00100 00101 if (f) { 00102 int err = fseek(f, off, SEEK_SET); 00103 if (err) { 00104 return -errno; 00105 } 00106 00107 size_t res = fread(data, 1, size, f); 00108 if (res < size && !feof(f)) { 00109 return -errno; 00110 } 00111 00112 err = fclose(f); 00113 if (err) { 00114 return -errno; 00115 } 00116 } 00117 00118 emu->stats.read_count += 1; 00119 return 0; 00120 } 00121 00122 int lfs_emubd_prog(const struct lfs_config *cfg, lfs_block_t block, 00123 lfs_off_t off, const void *buffer, lfs_size_t size) { 00124 lfs_emubd_t *emu = cfg->context; 00125 const uint8_t *data = buffer; 00126 00127 // Check if write is valid 00128 assert(off % cfg->prog_size == 0); 00129 assert(size % cfg->prog_size == 0); 00130 assert(block < cfg->block_count); 00131 00132 // Program data 00133 snprintf(emu->child, LFS_NAME_MAX, "%" PRIx32, block); 00134 00135 FILE *f = fopen(emu->path, "r+b"); 00136 if (!f) { 00137 return (errno == EACCES) ? 0 : -errno; 00138 } 00139 00140 // Check that file was erased 00141 assert(f); 00142 00143 int err = fseek(f, off, SEEK_SET); 00144 if (err) { 00145 return -errno; 00146 } 00147 00148 size_t res = fwrite(data, 1, size, f); 00149 if (res < size) { 00150 return -errno; 00151 } 00152 00153 err = fseek(f, off, SEEK_SET); 00154 if (err) { 00155 return -errno; 00156 } 00157 00158 uint8_t dat; 00159 res = fread(&dat, 1, 1, f); 00160 if (res < 1) { 00161 return -errno; 00162 } 00163 00164 err = fclose(f); 00165 if (err) { 00166 return -errno; 00167 } 00168 00169 emu->stats.prog_count += 1; 00170 return 0; 00171 } 00172 00173 int lfs_emubd_erase(const struct lfs_config *cfg, lfs_block_t block) { 00174 lfs_emubd_t *emu = cfg->context; 00175 00176 // Check if erase is valid 00177 assert(block < cfg->block_count); 00178 00179 // Erase the block 00180 snprintf(emu->child, LFS_NAME_MAX, "%" PRIx32, block); 00181 struct stat st; 00182 int err = stat(emu->path, &st); 00183 if (err && errno != ENOENT) { 00184 return -errno; 00185 } 00186 00187 if (!err && S_ISREG(st.st_mode) && (S_IWUSR & st.st_mode)) { 00188 err = unlink(emu->path); 00189 if (err) { 00190 return -errno; 00191 } 00192 } 00193 00194 if (err || (S_ISREG(st.st_mode) && (S_IWUSR & st.st_mode))) { 00195 FILE *f = fopen(emu->path, "w"); 00196 if (!f) { 00197 return -errno; 00198 } 00199 00200 err = fclose(f); 00201 if (err) { 00202 return -errno; 00203 } 00204 } 00205 00206 emu->stats.erase_count += 1; 00207 return 0; 00208 } 00209 00210 int lfs_emubd_sync(const struct lfs_config *cfg) { 00211 lfs_emubd_t *emu = cfg->context; 00212 00213 // Just write out info/stats for later lookup 00214 snprintf(emu->child, LFS_NAME_MAX, "config"); 00215 FILE *f = fopen(emu->path, "w"); 00216 if (!f) { 00217 return -errno; 00218 } 00219 00220 size_t res = fwrite(&emu->cfg, sizeof(emu->cfg), 1, f); 00221 if (res < 1) { 00222 return -errno; 00223 } 00224 00225 int err = fclose(f); 00226 if (err) { 00227 return -errno; 00228 } 00229 00230 snprintf(emu->child, LFS_NAME_MAX, "stats"); 00231 f = fopen(emu->path, "w"); 00232 if (!f) { 00233 return -errno; 00234 } 00235 00236 res = fwrite(&emu->stats, sizeof(emu->stats), 1, f); 00237 if (res < 1) { 00238 return -errno; 00239 } 00240 00241 err = fclose(f); 00242 if (err) { 00243 return -errno; 00244 } 00245 00246 return 0; 00247 }
Generated on Tue Jul 12 2022 13:54:26 by
