diff --git a/fs/mnemofs/CMakeLists.txt b/fs/mnemofs/CMakeLists.txt index c360c3eb9c5..79490363532 100644 --- a/fs/mnemofs/CMakeLists.txt +++ b/fs/mnemofs/CMakeLists.txt @@ -48,6 +48,12 @@ if(CONFIG_FS_MNEMOFS) target_sources( - fs PRIVATE mnemofs_blkalloc.c mnemofs_fsobj.c mnemofs_journal.c - mnemofs_lru.c mnemofs_rw.c mnemofs.c) + fs + PRIVATE mnemofs_blkalloc.c + mnemofs_fsobj.c + mnemofs_journal.c + mnemofs_lru.c + mnemofs_rw.c + mnemofs_util.c + mnemofs.c) endif() diff --git a/fs/mnemofs/Make.defs b/fs/mnemofs/Make.defs index 4b6d8fbc79b..97fe304c439 100644 --- a/fs/mnemofs/Make.defs +++ b/fs/mnemofs/Make.defs @@ -57,6 +57,7 @@ CSRCS += mnemofs_fsobj.c CSRCS += mnemofs_journal.c CSRCS += mnemofs_lru.c CSRCS += mnemofs_rw.c +CSRCS += mnemofs_util.c CSRCS += mnemofs.c # Add the mnemofs directory to the build diff --git a/fs/mnemofs/mnemofs.h b/fs/mnemofs/mnemofs.h index 93c647e4fdd..2dd0cbbdf66 100644 --- a/fs/mnemofs/mnemofs.h +++ b/fs/mnemofs/mnemofs.h @@ -734,6 +734,270 @@ int mfs_erase_blk(FAR const struct mfs_sb_s * const sb, const off_t blk); int mfs_erase_nblks(FAR const struct mfs_sb_s * const sb, const off_t blk, const size_t n); +/* mnemofs_util.c */ + +/**************************************************************************** + * Name: mfs_arrhash + * + * Description: + * Returns an 8-bit hash of an entire array of data. + * + * Input Parameters: + * arr - Data array. + * len - Length of the array. + * + * Returned Value: + * 16-bit hash of the array. + * + ****************************************************************************/ + +uint8_t mfs_arrhash(FAR const char *arr, ssize_t len); + +/**************************************************************************** + * Name: mfs_ser_8 + * + * Description: + * Serialize a 8 bit type into output. + * + * Input Parameters: + * n - 8 bit to serialize + * out - Output array where to serialize. + * + * Returned Value: + * Pointer to byte after the end of serialized value. + * + ****************************************************************************/ + +FAR char *mfs_ser_8(const uint8_t n, FAR char * const out); + +/**************************************************************************** + * Name: mfs_deser_8 + * + * Description: + * Deserialize a 8 bit type from input. + * + * Input Parameters: + * in - Input array from where to deserialize. + * n - 8 bit to deserialize + * + * Returned Value: + * Pointer to byte after the end of serialized value. + * + ****************************************************************************/ + +FAR const char *mfs_deser_8(FAR const char * const in, uint8_t *n); + +/**************************************************************************** + * Name: mfs_ser_str + * + * Description: + * Serialize a string into output. + * + * Input Parameters: + * str - String to serialize + * len - Length of string + * out - Output array where to serialize. + * + * Returned Value: + * Pointer to byte after the end of serialized value. + * + ****************************************************************************/ + +FAR char *mfs_ser_str(FAR const char * const str, const mfs_t len, + FAR char * const out); + +/**************************************************************************** + * Name: mfs_deser_str + * + * Description: + * Deserialize a string from intput. + * + * Input Parameters: + * in - Intput array from where to deserialize. + * str - String to deserialize + * len - Length of string + * + * Returned Value: + * Pointer to byte after the end of serialized value. + * + ****************************************************************************/ + +FAR const char *mfs_deser_str(FAR const char * const in, + FAR char * const str, const mfs_t len); + +/**************************************************************************** + * Name: mfs_ser_mfs + * + * Description: + * Serialize a mfs_t type into output. + * + * Input Parameters: + * n - mfs_t to serialize + * out - Output array where to serialize. + * + * Returned Value: + * Pointer to byte after the end of serialized value. + * + ****************************************************************************/ + +FAR char *mfs_ser_mfs(const mfs_t n, FAR char * const out); + +/**************************************************************************** + * Name: mfs_deser_mfs + * + * Description: + * Deserialize a mfs_t type from input.. + * + * Input Parameters: + * in - Input array from where to deserialize. + * n - mfs_t to deserialize + * + * Returned Value: + * Pointer to byte after the end of serialized value. + * + ****************************************************************************/ + +FAR const char *mfs_deser_mfs(FAR const char * const in, + FAR mfs_t * const n); + +/**************************************************************************** + * Name: mfs_ser_ctz + * + * Description: + * Serialize a mfs_ctz_store_s type into output. + * + * Input Parameters: + * x - mfs_ctz_s to serialize + * out - Output array where to serialize. + * + * Returned Value: + * Pointer to byte after the end of serialized value. + * + ****************************************************************************/ + +FAR char *mfs_ser_ctz(FAR const struct mfs_ctz_s * const x, + FAR char * const out); + +/**************************************************************************** + * Name: mfs_deser_ctz + * + * Description: + * Deserialize a mfs_ctz_store_s type into output. + * + * Input Parameters: + * in - Input array from where to deserialize. + * x - mfs_ctz_s to deserialize + * + * Returned Value: + * Pointer to byte after the end of serialized value. + * + ****************************************************************************/ + +FAR const char *mfs_deser_ctz(FAR const char * const in, + FAR struct mfs_ctz_s * const x); + +/**************************************************************************** + * Name: mfs_ser_timespec + * + * Description: + * Serialize timespec. + * + * Input Parameters: + * x - Value to serialize + * out - Output array where to serialize. + * + * Returned Value: + * Pointer to byte after the end of serialized value. + * + ****************************************************************************/ + +FAR char *mfs_ser_timespec(FAR const struct timespec * const x, + FAR char * const out); + +/**************************************************************************** + * Name: mfs_deser_timespec + * + * Description: + * Deserialize timespec. + * + * Input Parameters: + * in - Input array from where to deserialize. + * x - Value to deserialize + * + * Returned Value: + * Pointer to byte after the end of serialized value. + * + ****************************************************************************/ + +FAR const char *mfs_deser_timespec(FAR const char * const in, + FAR struct timespec * const x); + +/**************************************************************************** + * Name: mfs_ser_16 + * + * Description: + * Serialize 16 bit values. + * + * Input Parameters: + * x - Value to serialize + * out - Output array where to serialize. + * + * Returned Value: + * Pointer to byte after the end of serialized value. + * + ****************************************************************************/ + +FAR char *mfs_ser_16(const uint16_t n, FAR char * const out); + +/**************************************************************************** + * Name: mfs_deser_16 + * + * Description: + * Deserialize 16 bit value. + * + * Input Parameters: + * in - Input array from where to deserialize. + * x - Value to deserialize + * + * Returned Value: + * Pointer to byte after the end of serialized value. + * + ****************************************************************************/ + +FAR const char *mfs_deser_16(FAR const char * const in, FAR uint16_t *n); + +/**************************************************************************** + * Name: mfs_v2n + * + * Description: + * v2n(n) math function. + * + * Input Parameters: + * n - Number. + * + * Returned Value: + * v2n(n). + * + ****************************************************************************/ + +mfs_t mfs_v2n(mfs_t n); + +/**************************************************************************** + * Name: mfs_set_msb + * + * Description: + * Set the least significant of the most significant unset bits. + * + * Input Parameters: + * n - Number. + * + * Returned Value: + * Number after setting the bit. + * + ****************************************************************************/ + +mfs_t mfs_set_msb(mfs_t n); + /* mnemofs_lru.c */ /**************************************************************************** diff --git a/fs/mnemofs/mnemofs_fsobj.c b/fs/mnemofs/mnemofs_fsobj.c index d6e8ce0eb8e..aea7ccd51db 100644 --- a/fs/mnemofs/mnemofs_fsobj.c +++ b/fs/mnemofs/mnemofs_fsobj.c @@ -79,6 +79,13 @@ * Private Function Prototypes ****************************************************************************/ +static mfs_t nobjs_in_path(FAR const char * relpath); +static const char *next_child(FAR const char *relpath); +static FAR char *mfs_ser_dirent(FAR const struct mfs_dirent_s * const x, + FAR char * const out); +static FAR const char *mfs_deser_dirent(FAR const char * const in, + FAR struct mfs_dirent_s * const x); + /**************************************************************************** * Private Data ****************************************************************************/ @@ -91,131 +98,623 @@ * Private Functions ****************************************************************************/ +/**************************************************************************** + * Name: nobjs_in_path + * + * Description: + * Count number of file system objects in path. This includes root in the + * count. + * + * Input Parameters: + * relpath - Relative Path. + * + * Returned Value: + * The number of file system objects in the path including the root. + * + ****************************************************************************/ + +static mfs_t nobjs_in_path(FAR const char *relpath) +{ + mfs_t count; + + if (*relpath == 0) + { + return 1; + } + + count = 2; + + while (*relpath == 0) + { + if (*relpath == '/') + { + count++; + } + + relpath++; + } + + return count; +} + +/**************************************************************************** + * Name: nobjs_in_path + * + * Description: + * Give the pointer to next child that appears in the path. + * + * Input Parameters: + * relpath - Relative Path. + * + * Returned Value: + * The pointer to the next child. This is not allocated, but points to the + * inside relpath itself. + * + ****************************************************************************/ + +static const char *next_child(FAR const char *relpath) +{ + while (*relpath != 0) + { + if (*relpath == '/') + { + return relpath + 1; + } + + relpath++; + } + + return NULL; +} + +/**************************************************************************** + * Name: mfs_ser_dirent + * + * Description: + * Serialize a direntry. + * + * Input Parameters: + * x - Direntry. + * out - Buffer to populate. + * + * Returned Value: + * Pointer to after the end of serialized content in out. + * + ****************************************************************************/ + +static FAR char *mfs_ser_dirent(FAR const struct mfs_dirent_s * const x, + FAR char * const out) +{ + FAR char *o = out; + + o = mfs_ser_8(x->name_hash, o); + o = mfs_ser_mfs(x->sz, o); + o = mfs_ser_mfs((mfs_t) x->mode, o); + o = mfs_ser_timespec(&x->st_atim, o); + o = mfs_ser_timespec(&x->st_mtim, o); + o = mfs_ser_timespec(&x->st_ctim, o); + o = mfs_ser_ctz(&x->ctz, o); + o = mfs_ser_8(x->namelen, o); + o = mfs_ser_str(x->name, x->namelen, o); + + return o; +} + +/**************************************************************************** + * Name: mfs_deser_dirent + * + * Description: + * Deserialize a direntry. + * + * Input Parameters: + * in - Buffer. + * x - Direntry to populate. + * + * Returned Value: + * Pointer to after the end of deserialized content in in. + * + ****************************************************************************/ + +static FAR const char *mfs_deser_dirent(FAR const char * const in, + FAR struct mfs_dirent_s * const x) +{ + FAR const char *i = in; + + i = mfs_deser_8(i, &x->name_hash); + i = mfs_deser_mfs(i, &x->sz); + i = mfs_deser_mfs(i, (mfs_t *) &x->mode); + i = mfs_deser_timespec(i, &x->st_atim); + i = mfs_deser_timespec(i, &x->st_mtim); + i = mfs_deser_timespec(i, &x->st_ctim); + i = mfs_deser_ctz(i, &x->ctz); + i = mfs_deser_8(i, &x->namelen); + i = mfs_deser_str(i, x->name, x->namelen); + + return i; +} + /**************************************************************************** * Public Function Prototypes ****************************************************************************/ FAR const char * mfs_path2childname(FAR const char *relpath) { - /* TODO */ + FAR const char *last = relpath + strlen(relpath) - 1; - return NULL; + while (last >= relpath && *last != '/') + { + last--; + } + + return last + 1; } mfs_t mfs_get_fsz(FAR struct mfs_sb_s * const sb, FAR const struct mfs_path_s * const path, const mfs_t depth) { - /* TODO */ + mfs_t sz; - return 0; + if (depth == 0) + { + /* Master node. */ + + return 0; + } + else if (depth == 1) + { + sz = MFS_MN(sb).root_sz; + mfs_lru_updatedsz(sb, path, depth, &sz); + +/* Journal updated to the root creates a new master node entry. TODO + * this and moving of the journal. + */ + + finfo("File size got as %u for root.", sz); + return sz; + } + + return path[depth - 1].sz; } int mfs_get_patharr(FAR struct mfs_sb_s *const sb, FAR const char *relpath, FAR struct mfs_path_s **path, FAR mfs_t *depth) { - /* TODO */ + int ret; + bool found; + bool isfile; + mfs_t sz; + mfs_t idx; + uint8_t hash; + const mfs_t len = nobjs_in_path(relpath); + FAR const char *next; + struct mfs_pitr_s pitr; + FAR struct mfs_dirent_s *dirent; - return OK; + ret = 0; + idx = 0; + isfile = false; + found = true; + + *path = kmm_zalloc(len * sizeof(struct mfs_ctz_s)); + if (predict_false(*path == NULL)) + { + return -ENOMEM; + } + + *depth = len; + (*path)[idx].ctz = MFS_MN(sb).root_ctz; + (*path)[idx].off = 0; + (*path)[idx].sz = mfs_get_fsz(sb, *path, 1); + + finfo("Path \"%s\" depth %u.", relpath, len); + + if (len == 1) + { + ret |= MFS_P_EXIST | MFS_P_ISDIR | MFS_ISDIR; + goto errout; + } + else if (len == 2) + { + ret |= MFS_P_EXIST | MFS_P_ISDIR; + } + + for (idx = 1; idx < len; idx++) + { + mfs_pitr_init(sb, *path, idx - 1, &pitr, false); + + if (predict_false(idx == 1)) + { + next = relpath; + } + else + { + next = next_child(relpath); + } + + sz = next - relpath; + hash = mfs_arrhash(relpath, sz); + + for (; ; ) + { + mfs_pitr_readdirent(sb, &pitr, &dirent); + if (predict_false(dirent == NULL)) + { + found = false; + ret |= MFS_NEXIST; + break; + } + + if (dirent->name_hash == hash && + !strncmp(dirent->name, relpath, sz)) + { + (*path)[idx - 1].ctz = dirent->ctz; + (*path)[idx - 1].off = pitr.c_off; + (*path)[idx - 1].sz = dirent->sz; + + mfs_free_dirent(dirent); + + if (len >= 2 && idx == len - 2) + { + ret |= MFS_P_EXIST; + ret |= (S_ISDIR(dirent->mode) ? MFS_P_ISDIR : + (MFS_FINPATH | MFS_NEXIST)); + } + else if (idx == len - 1) + { + ret |= (S_ISDIR(dirent->mode) ? MFS_ISDIR : MFS_ISFILE); + } + else + { + ret |= (S_ISDIR(dirent->mode) ? 0 : + (MFS_FINPATH | MFS_NEXIST)); + } + + break; + } + + if (!S_ISDIR(dirent->mode)) + { + isfile = true; + } + + mfs_pitr_adv_dirent(&pitr, dirent); + + mfs_free_dirent(dirent); + + if (isfile) + { + /* At max, only the last element is allowed to be a file. */ + + break; + } + } + + mfs_pitr_free(&pitr); + + if (!found) + { + break; + } + + relpath = next; + finfo("Next path \"%s\"", relpath); + } + +errout: + finfo("Path array for \"%s\", returned flags: %u.", relpath, ret); + return ret; } void mfs_free_patharr(FAR struct mfs_path_s *path) { - /* TODO */ + kmm_free(path); } bool mfs_obj_isempty(FAR struct mfs_sb_s * const sb, - FAR struct mfs_pitr_s * const pitr) + FAR struct mfs_pitr_s * const pitr) { - /* TODO */ + FAR struct mfs_dirent_s *dirent = NULL; + bool ret; - return false; + mfs_pitr_readdirent(sb, pitr, &dirent); + ret = (dirent->sz == 0); + mfs_free_dirent(dirent); + + return ret; } void mfs_pitr_init(FAR struct mfs_sb_s * const sb, - FAR const struct mfs_path_s * const path, - const mfs_t depth, FAR struct mfs_pitr_s *pitr, bool child) + FAR const struct mfs_path_s * const path, + const mfs_t depth, FAR struct mfs_pitr_s *pitr, + bool child) { - /* TODO */ + const uint8_t diff = child ? 1 : 0; + mfs_t p_depth; + + if (predict_false(depth < diff)) + { + return; + } + + p_depth = depth - diff; + + if (p_depth == 0) + { + /* Master Node */ + + pitr->sz = 0; + memset(&pitr->p, 0, sizeof(pitr->p)); + } + else + { + pitr->p.ctz = path[p_depth - 1].ctz; + pitr->sz = path[p_depth - 1].sz; + } + + pitr->depth = p_depth; + pitr->c_off = 0; + + finfo("Pitr initialized for parent CTZ at (%u, %u) at" + " depth %u for file size %u.", + pitr->p.ctz.idx_e, pitr->p.ctz.pg_e, pitr->depth, pitr->sz); } void mfs_pitr_free(FAR struct mfs_pitr_s * const pitr) { - /* TODO */ + finfo("Pitr for CTZ (%u, %u) at depth %u freed.", + pitr->p.ctz.idx_e, pitr->p.ctz.pg_e, pitr->depth); + + memset(pitr, 0, sizeof(*pitr)); } void mfs_pitr_adv(FAR struct mfs_sb_s * const sb, FAR struct mfs_pitr_s * const pitr) { - /* TODO */ + FAR struct mfs_dirent_s *dirent; + + mfs_pitr_readdirent(sb, pitr, &dirent); + mfs_pitr_adv_dirent(pitr, dirent); + mfs_free_dirent(dirent); + + finfo("Pitr for CTZ (%u, %u) advanced to offset %u.", + pitr->p.ctz.idx_e, pitr->p.ctz.pg_e, pitr->c_off); } void mfs_pitr_adv_dirent(FAR struct mfs_pitr_s * const pitr, - FAR const struct mfs_dirent_s * const dirent) + FAR const struct mfs_dirent_s * const dirent) { - /* TODO */ + pitr->c_off += MFS_DIRENTSZ(dirent); + + finfo("Pitr for CTZ (%u, %u) advanced to offset %u using dirent.", + pitr->p.ctz.idx_e, pitr->p.ctz.pg_e, pitr->c_off); } void mfs_pitr_adv_off(FAR struct mfs_pitr_s * const pitr, const mfs_t off) { - /* TODO */ + pitr->c_off += off; + + finfo("Pitr for CTZ (%u, %u) advanced to offset %u by offset %u.", + pitr->p.ctz.idx_e, pitr->p.ctz.pg_e, pitr->c_off, off); } void mfs_pitr_adv_tochild(FAR struct mfs_pitr_s * const pitr, FAR const struct mfs_path_s * const path, const mfs_t depth) { - /* TODO */ + if (pitr->depth == 0) + { + return; + } + + pitr->c_off = path[depth - 1].off; + + finfo("Pitr for CTZ (%u, %u) at depth %u advanced to offset %u.", + pitr->p.ctz.idx_e, pitr->p.ctz.pg_e, depth, path[depth - 1].off); } void mfs_pitr_reset(FAR struct mfs_pitr_s * const pitr) { - /* TODO */ + pitr->c_off = 0; + + finfo("Pitr for CTZ (%u, %u) reset.", + pitr->p.ctz.idx_e, pitr->p.ctz.pg_e); } void mfs_pitr_sync(FAR struct mfs_sb_s * const sb, - FAR struct mfs_pitr_s * const pitr, - FAR const struct mfs_path_s * const path, - const mfs_t depth) + FAR struct mfs_pitr_s * const pitr, + FAR const struct mfs_path_s * const path, + const mfs_t depth) { - /* TODO */ + finfo("Pitr for CTZ (%u, %u) syncing...", + pitr->p.ctz.idx_e, pitr->p.ctz.pg_e); + + /* TODO: mfs_jrnl_updatectz(sb, &pitr->p.ctz, pitr->depth); */ + + pitr->sz = mfs_get_fsz(sb, path, depth - 1); + + DEBUGASSERT(depth == pitr->depth); + + finfo("New location is (%u, %u).", + pitr->p.ctz.idx_e, pitr->p.ctz.pg_e); } int mfs_pitr_readdirent(FAR struct mfs_sb_s * const sb, FAR struct mfs_pitr_s * const pitr, FAR struct mfs_dirent_s **dirent) { - /* TODO */ + int ret = OK; + mfs_t sz = 0; + const mfs_t len = sizeof(struct mfs_dirent_s) + + NAME_MAX + 1; + char dirent_data[len]; + struct mfs_dirent_s *dirent_rd = NULL; - return OK; + /* No harm in reading more. The namelen will stop all the included + * unnecessary characters during deserialization, and if there are none, + * the rest will be just empty. + */ + + memset(dirent_data, 0, len); + + *dirent = NULL; + + dirent_rd = kmm_zalloc(len); + if (predict_false(dirent_rd == NULL)) + { + goto errout; + } + + if (pitr->depth == 0) + { + dirent_rd->ctz = MFS_MN(sb).root_ctz; + dirent_rd->mode = MFS_MN(sb).root_mode; + dirent_rd->st_atim = MFS_MN(sb).root_st_atim; + dirent_rd->st_ctim = MFS_MN(sb).root_st_ctim; + dirent_rd->st_mtim = MFS_MN(sb).root_st_mtim; + dirent_rd->mode = MFS_MN(sb).root_mode; + dirent_rd->sz = MFS_MN(sb).root_sz; + dirent_rd->namelen = 1; + dirent_rd->name_hash = 0; + + memcpy(dirent_rd->name, "", 2); + } + else + { + mfs_lru_rdfromoff(sb, pitr->c_off, &pitr->p, pitr->depth, + dirent_data, len); + mfs_deser_dirent(dirent_data, dirent_rd); + + finfo("Got direntry with name %s", dirent_rd->name); + } + + sz = MFS_DIRENTSZ(dirent_rd); + if (dirent_rd->namelen == 0) + { + /* Not found direntry. */ + + goto errout_with_dirent_rd; + } + + *dirent = kmm_zalloc(sz); + if (predict_false(*dirent == NULL)) + { + ret = -ENOMEM; + goto errout_with_dirent_rd; + } + + memcpy(*dirent, dirent_rd, sz); + +errout_with_dirent_rd: + kmm_free(dirent_rd); + + if (ret < 0) + { + finfo("Direntry could not be allocated."); + } + else if (*dirent == NULL) + { + finfo("No direntry found."); + } + else + { + finfo("Reading direntry done for %s.", (*dirent)->name); + } + +errout: + return ret; } void mfs_free_dirent(FAR struct mfs_dirent_s *dirent) { - /* TODO */ + kmm_free(dirent); + + finfo("Dirent freed."); } bool mfs_searchfopen(FAR const struct mfs_sb_s * const sb, - FAR const struct mfs_path_s * const path, - const mfs_t depth) + FAR const struct mfs_path_s * const path, + const mfs_t depth) { - /* TODO */ + FAR struct mfs_ofd_s *ofd = NULL; + + list_for_every_entry(&sb->of, ofd, struct mfs_ofd_s, list) + { + if (ofd->com->depth != depth) + { + continue; + } + + /* TODO: Ensure when an LRU's delta is flushed to the journal, the + * new location is updated in the LRU AND the open files, if it is + * open. + */ + + if (ofd->com->path[depth - 1].off == path[depth - 1].off && + ofd->com->path[depth - 1].ctz.pg_e == path[depth - 1].ctz.pg_e && + ofd->com->path[depth - 1].ctz.idx_e == path[depth - 1].ctz.idx_e) + { + return true; + } + } return false; } int mfs_pitr_appendnew(FAR struct mfs_sb_s * const sb, - FAR struct mfs_path_s * const path, - const mfs_t depth, - FAR const struct mfs_pitr_s * const pitr, - FAR const char * const child_name, - const mode_t mode) + FAR struct mfs_path_s * const path, + const mfs_t depth, + FAR const struct mfs_pitr_s * const pitr, + FAR const char * const child_name, + const mode_t mode) { - /* TODO */ + int ret = OK; + mfs_t len; + mfs_t pg; + struct mfs_dirent_s *dirent = NULL; + struct timespec ts; - return OK; + len = strlen(child_name); + + dirent = kmm_zalloc(sizeof(*dirent) + len); + if (predict_false(dirent == NULL)) + { + return -ENOMEM; + } + + clock_gettime(CLOCK_REALTIME, &ts); + + /* TODO: Confirm if creation for directory in VFS gives true for + * S_ISDIR(). + */ + + pg = mfs_ba_getpg(sb); + if (predict_false(pg == 0)) + { + return -ENOSPC; + } + + dirent->sz = 0; + dirent->mode = mode; + dirent->ctz.pg_e = pg; + dirent->ctz.idx_e = 0; + dirent->st_atim = ts; + dirent->st_mtim = ts; + dirent->st_ctim = ts; + dirent->namelen = len; + strncpy(dirent->name, child_name, len); + + ret = mfs_pitr_appenddirent(sb, path, depth, pitr, dirent); + finfo("New direntry %p with name \"%s\" appended to CTZ (%u, %u) " + "at offset %u depth %u.", + dirent, dirent->name, pitr->p.ctz.idx_e, pitr->p.ctz.pg_e, + pitr->c_off, pitr->depth); + + mfs_free_dirent(dirent); + + return ret; } int mfs_pitr_appenddirent(FAR struct mfs_sb_s * const sb, @@ -224,9 +723,28 @@ int mfs_pitr_appenddirent(FAR struct mfs_sb_s * const sb, FAR const struct mfs_pitr_s * const pitr, FAR const struct mfs_dirent_s * const dirent) { - /* TODO */ + int ret = OK; + const mfs_t len = MFS_DIRENTSZ(dirent); + char dirent_data[len]; + struct mfs_pitr_s p_pitr; + FAR struct mfs_dirent_s *p_dirent = NULL; - return OK; + memset(dirent_data, 0, len); + mfs_ser_dirent(dirent, dirent_data); + + mfs_pitr_init(sb, path, depth - 1, &p_pitr, true); + mfs_pitr_adv_tochild(&p_pitr, path, depth - 1); + mfs_pitr_readdirent(sb, &p_pitr, &p_dirent); + + ret = mfs_lru_wr(sb, p_dirent->sz, len, p_dirent->sz, path, depth - 1, + dirent_data); + + mfs_free_dirent(p_dirent); + mfs_pitr_free(&p_pitr); + + finfo("Appended direntry for \"%s\" at depth %u.", dirent->name, depth); + + return ret; } int mfs_pitr_rmdirent(FAR struct mfs_sb_s * const sb, @@ -235,16 +753,36 @@ int mfs_pitr_rmdirent(FAR struct mfs_sb_s * const sb, FAR struct mfs_pitr_s * const pitr, FAR const struct mfs_dirent_s * const dirent) { - /* TODO */ + FAR struct mfs_dirent_s *p_dirent = NULL; + struct mfs_pitr_s p_pitr; + int ret = OK; - return OK; + mfs_pitr_init(sb, path, depth - 1, &p_pitr, true); + mfs_pitr_adv_tochild(&p_pitr, path, depth - 1); + mfs_pitr_readdirent(sb, &p_pitr, &p_dirent); + + ret = mfs_lru_del(sb, pitr->c_off, MFS_DIRENTSZ(dirent), p_dirent->sz, + path, depth); + + mfs_free_dirent(p_dirent); + mfs_pitr_free(&p_pitr); + + return ret; } int mfs_pitr_rm(FAR struct mfs_sb_s * const sb, FAR struct mfs_path_s * const path, const mfs_t depth) { - /* TODO */ + int ret = OK; + struct mfs_pitr_s pitr; + FAR struct mfs_dirent_s *dirent = NULL; - return OK; + mfs_pitr_init(sb, path, depth, &pitr, true); + mfs_pitr_readdirent(sb, &pitr, &dirent); + ret = mfs_pitr_rmdirent(sb, path, depth, &pitr, dirent); + mfs_free_dirent(dirent); + mfs_pitr_free(&pitr); + + return ret; } diff --git a/fs/mnemofs/mnemofs_util.c b/fs/mnemofs/mnemofs_util.c new file mode 100644 index 00000000000..9227ea09be0 --- /dev/null +++ b/fs/mnemofs/mnemofs_util.c @@ -0,0 +1,227 @@ +/**************************************************************************** + * fs/mnemofs/mnemofs_util.c + * Utilities for mnemofs + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Alternatively, the contents of this file may be used under the terms of + * the BSD-3-Clause license: + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 2024 Saurav Pal + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of its contributors may + * be used to endorse or promote products derived from this software + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include "mnemofs.h" + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +uint8_t mfs_arrhash(FAR const char *arr, ssize_t len) +{ + ssize_t l = 0; + ssize_t r = len - 1; + uint16_t hash = 0; + + while (l <= r) + { + hash += arr[l] * arr[r] * (l + 1) * (r + 1); + l++; + r--; + hash %= (1 << 8); + } + + finfo("Hash calculated for size %ld to be %d.", len, hash % (1 << 8)); + + return hash % (1 << 8); +} + +FAR char *mfs_ser_8(const uint8_t n, FAR char * const out) +{ + *out = n; + return out + 1; +} + +FAR const char *mfs_deser_8(FAR const char * const in, FAR uint8_t *n) +{ + *n = in[0]; + return in + 1; +} + +FAR char *mfs_ser_16(const uint16_t n, FAR char * const out) +{ + memcpy(out, &n, 2); + return out + 2; +} + +FAR const char *mfs_deser_16(FAR const char * const in, FAR uint16_t *n) +{ + memcpy(n, in, 2); + return in + 2; +} + +FAR char *mfs_ser_str(FAR const char * const str, const mfs_t len, + FAR char * const out) +{ + memcpy(out, str, len); + return out + len; +} + +FAR const char *mfs_deser_str(FAR const char * const in, + FAR char * const str, const mfs_t len) +{ + memcpy(str, in, len); + str[len] = 0; + return in + len; +} + +FAR char *mfs_ser_mfs(const mfs_t n, FAR char * const out) +{ + memcpy(out, &n, 4); + return out + 4; +} + +FAR const char *mfs_deser_mfs(FAR const char * const in, FAR mfs_t * const n) +{ + memcpy(n, in, 4); + return in + 4; +} + +FAR char *mfs_ser_64(const uint64_t n, FAR char * const out) +{ + memcpy(out, &n, 8); + return out + 8; +} + +FAR const char *mfs_deser_64(FAR const char * const in, + FAR uint64_t * const n) +{ + memcpy(n, in, 8); + return in + 8; +} + +FAR char *mfs_ser_ctz(FAR const struct mfs_ctz_s * const x, + FAR char * const out) +{ + char *o = out; + + o = mfs_ser_mfs(x->pg_e, o); + o = mfs_ser_mfs(x->idx_e, o); + return o; +} + +FAR const char *mfs_deser_ctz(FAR const char * const in, + FAR struct mfs_ctz_s * const x) +{ + const char *i = in; + + i = mfs_deser_mfs(i, &x->pg_e); + i = mfs_deser_mfs(i, &x->idx_e); + return i; +} + +FAR char *mfs_ser_timespec(FAR const struct timespec * const x, + FAR char * const out) +{ + char *o = out; + + o = mfs_ser_64(x->tv_sec, o); + o = mfs_ser_64(x->tv_nsec, o); + + return o; +} + +FAR const char *mfs_deser_timespec(FAR const char * const in, + FAR struct timespec * const x) +{ + uint64_t tmp; + const char *i = in; + + i = mfs_deser_64(i, &tmp); + x->tv_sec = tmp; + i = mfs_deser_64(i, &tmp); + x->tv_nsec = tmp; + + return i; +} + +mfs_t mfs_v2n(mfs_t n) +{ + /* https://math.stackexchange.com/a/1835555 */ + + return (n & (~(n - 1))); +} + +mfs_t set_msb(mfs_t n) +{ + return 31 - mfs_clz(n); +}