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