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.
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 FILE *f = fopen(emu->path, "r"); 00051 if (!f) { 00052 return -errno; 00053 } 00054 00055 size_t res = fread(&emu->stats, sizeof(emu->stats), 1, f); 00056 if (res < 1) { 00057 return -errno; 00058 } 00059 00060 err = fclose(f); 00061 if (err) { 00062 return -errno; 00063 } 00064 00065 return 0; 00066 } 00067 00068 void lfs_emubd_destroy(const struct lfs_config *cfg) { 00069 lfs_emubd_sync(cfg); 00070 00071 lfs_emubd_t *emu = cfg->context; 00072 free(emu->path); 00073 } 00074 00075 int lfs_emubd_read(const struct lfs_config *cfg, lfs_block_t block, 00076 lfs_off_t off, void *buffer, lfs_size_t size) { 00077 lfs_emubd_t *emu = cfg->context; 00078 uint8_t *data = buffer; 00079 00080 // Check if read is valid 00081 assert(off % cfg->read_size == 0); 00082 assert(size % cfg->read_size == 0); 00083 assert(block < cfg->block_count); 00084 00085 // Zero out buffer for debugging 00086 memset(data, 0, size); 00087 00088 // Read data 00089 snprintf(emu->child, LFS_NAME_MAX, "%" PRIx32, block); 00090 00091 FILE *f = fopen(emu->path, "rb"); 00092 if (!f && errno != ENOENT) { 00093 return -errno; 00094 } 00095 00096 if (f) { 00097 int err = fseek(f, off, SEEK_SET); 00098 if (err) { 00099 return -errno; 00100 } 00101 00102 size_t res = fread(data, 1, size, f); 00103 if (res < size && !feof(f)) { 00104 return -errno; 00105 } 00106 00107 err = fclose(f); 00108 if (err) { 00109 return -errno; 00110 } 00111 } 00112 00113 emu->stats.read_count += 1; 00114 return 0; 00115 } 00116 00117 int lfs_emubd_prog(const struct lfs_config *cfg, lfs_block_t block, 00118 lfs_off_t off, const void *buffer, lfs_size_t size) { 00119 lfs_emubd_t *emu = cfg->context; 00120 const uint8_t *data = buffer; 00121 00122 // Check if write is valid 00123 assert(off % cfg->prog_size == 0); 00124 assert(size % cfg->prog_size == 0); 00125 assert(block < cfg->block_count); 00126 00127 // Program data 00128 snprintf(emu->child, LFS_NAME_MAX, "%" PRIx32, block); 00129 00130 FILE *f = fopen(emu->path, "r+b"); 00131 if (!f) { 00132 return (errno == EACCES) ? 0 : -errno; 00133 } 00134 00135 // Check that file was erased 00136 assert(f); 00137 00138 int err = fseek(f, off, SEEK_SET); 00139 if (err) { 00140 return -errno; 00141 } 00142 00143 size_t res = fwrite(data, 1, size, f); 00144 if (res < size) { 00145 return -errno; 00146 } 00147 00148 err = fseek(f, off, SEEK_SET); 00149 if (err) { 00150 return -errno; 00151 } 00152 00153 uint8_t dat; 00154 res = fread(&dat, 1, 1, f); 00155 if (res < 1) { 00156 return -errno; 00157 } 00158 00159 err = fclose(f); 00160 if (err) { 00161 return -errno; 00162 } 00163 00164 emu->stats.prog_count += 1; 00165 return 0; 00166 } 00167 00168 int lfs_emubd_erase(const struct lfs_config *cfg, lfs_block_t block) { 00169 lfs_emubd_t *emu = cfg->context; 00170 00171 // Check if erase is valid 00172 assert(block < cfg->block_count); 00173 00174 // Erase the block 00175 snprintf(emu->child, LFS_NAME_MAX, "%" PRIx32, block); 00176 struct stat st; 00177 int err = stat(emu->path, &st); 00178 if (err && errno != ENOENT) { 00179 return -errno; 00180 } 00181 00182 if (!err && S_ISREG(st.st_mode) && (S_IWUSR & st.st_mode)) { 00183 err = unlink(emu->path); 00184 if (err) { 00185 return -errno; 00186 } 00187 } 00188 00189 if (err || (S_ISREG(st.st_mode) && (S_IWUSR & st.st_mode))) { 00190 FILE *f = fopen(emu->path, "w"); 00191 if (!f) { 00192 return -errno; 00193 } 00194 00195 err = fclose(f); 00196 if (err) { 00197 return -errno; 00198 } 00199 } 00200 00201 emu->stats.erase_count += 1; 00202 return 0; 00203 } 00204 00205 int lfs_emubd_sync(const struct lfs_config *cfg) { 00206 lfs_emubd_t *emu = cfg->context; 00207 00208 // Just write out info/stats for later lookup 00209 snprintf(emu->child, LFS_NAME_MAX, "config"); 00210 FILE *f = fopen(emu->path, "w"); 00211 if (!f) { 00212 return -errno; 00213 } 00214 00215 size_t res = fwrite(&emu->cfg, sizeof(emu->cfg), 1, f); 00216 if (res < 1) { 00217 return -errno; 00218 } 00219 00220 int err = fclose(f); 00221 if (err) { 00222 return -errno; 00223 } 00224 00225 snprintf(emu->child, LFS_NAME_MAX, "stats"); 00226 f = fopen(emu->path, "w"); 00227 if (!f) { 00228 return -errno; 00229 } 00230 00231 res = fwrite(&emu->stats, sizeof(emu->stats), 1, f); 00232 if (res < 1) { 00233 return -errno; 00234 } 00235 00236 err = fclose(f); 00237 if (err) { 00238 return -errno; 00239 } 00240 00241 return 0; 00242 }
Generated on Tue Aug 9 2022 00:37:09 by
1.7.2