diff --git a/lfs.c b/lfs.c index ea7e7e8d..176af574 100644 --- a/lfs.c +++ b/lfs.c @@ -1351,6 +1351,7 @@ static int lfsr_bd_cpyck(lfs_t *lfs, // return sizeof(tag) + lfs_tag_size(tag + lfs_tag_isdelete(tag)); //} +/// lfsr_tag_t stuff /// // 16-bit metadata tags enum lfsr_tag { @@ -9496,69 +9497,95 @@ enum { LFSR_DID_ROOT = 0, }; -// lookup full paths in our mtree +// some operations on paths +static inline lfs_size_t lfsr_path_namelen(const char *path) { + return lfs_strcspn(path, "/"); +} + +static inline bool lfsr_path_islast(const char *path) { + lfs_size_t name_len = lfsr_path_namelen(path); + return path[name_len + lfs_strspn(path + name_len, "/")] == '\0'; +} + +static inline bool lfsr_path_isdir(const char *path) { + return path[lfsr_path_namelen(path)] != '\0'; +} + +// lookup a full path in our mtree, updating the path as we descend // -// note the errors here are a bit weird, because paths can have some weird -// corner-cases during lookup, and we want to report all the different -// conditions: +// the errors get a bit subtle here, and rely on what ends up in the +// path/mdir: +// - 0 => file found +// - 0, lfsr_path_isdir(path) => dir found +// - 0, mdir.mid=-1 => root found +// - LFS_ERR_NOENT, lfsr_path_islast(path) => file not found +// - LFS_ERR_NOENT, !lfsr_path_islast(path) => parent not found +// - LFS_ERR_NOTDIR => parent not a dir // -// - 0 => path is valid, file NOT found -// - EXIST => path is valid, file found -// - INVAL => path is valid, but points to root -// - NOENT => path is NOT valid, intermediate dir missing -// - NOTDIR => path is NOT valid, intermediate dir is not a dir +// if not found, mdir_/did_ will at least be set up with what should be +// the parent // -// if not found, mdir_/did_/name_ will at least be set up -// with what should be the parent -static int lfsr_mtree_pathlookup(lfs_t *lfs, const char *path, - lfsr_mdir_t *mdir_, lfsr_tag_t *tag_, - lfsr_did_t *did_, const char **name_, lfs_size_t *name_size_) { +static int lfsr_mtree_pathlookup(lfs_t *lfs, const char **path, + lfsr_mdir_t *mdir_, lfsr_tag_t *tag_, lfsr_did_t *did_) { // setup root lfsr_mdir_t mdir = lfs->mroot; lfsr_tag_t tag = LFSR_TAG_DIR; lfsr_did_t did = LFSR_DID_ROOT; // we reduce path to a single name if we can find it - const char *name = path; - lfs_size_t name_size = 0; - while (true) { - // skip slashes - path += lfs_strspn(path, "/"); - lfs_size_t name_size__ = lfs_strcspn(path, "/"); + const char *path_ = *path; - // skip '.' and root '..' - if ((name_size__ == 1 && lfs_memcmp(path, ".", 1) == 0) - || (name_size__ == 2 && lfs_memcmp(path, "..", 2) == 0)) { - path += name_size__; + // empty paths are not allowed + if (path_[0] == '\0') { + return LFS_ERR_INVAL; + } + + while (true) { + // skip slashes if we're a directory + if (tag == LFSR_TAG_DIR) { + path_ += lfs_strspn(path_, "/"); + } + lfs_size_t name_len = lfs_strcspn(path_, "/"); + + // skip '.' + if (name_len == 1 && lfs_memcmp(path_, ".", 1) == 0) { + path_ += name_len; goto next; } + // error on unmatched '..', trying to go above root, eh? + if (name_len == 2 && lfs_memcmp(path_, "..", 2) == 0) { + return LFS_ERR_INVAL; + } + // skip if matched by '..' in name - const char *suffix = path + name_size__; - lfs_size_t suffix_size; + const char *suffix = path_ + name_len; + lfs_size_t suffix_len; int depth = 1; while (true) { suffix += lfs_strspn(suffix, "/"); - suffix_size = lfs_strcspn(suffix, "/"); - if (suffix_size == 0) { + suffix_len = lfs_strcspn(suffix, "/"); + if (suffix_len == 0) { break; } - if (suffix_size == 2 && lfs_memcmp(suffix, "..", 2) == 0) { + if (suffix_len == 1 && lfs_memcmp(suffix, ".", 1) == 0) { + // noop + } else if (suffix_len == 2 && lfs_memcmp(suffix, "..", 2) == 0) { depth -= 1; if (depth == 0) { - path = suffix + suffix_size; + path_ = suffix + suffix_len; goto next; } } else { depth += 1; } - suffix += suffix_size; + suffix += suffix_len; } // found end of path, we must be done parsing our path now - if (path[0] == '\0') { + if (path_[0] == '\0') { if (mdir_) { *mdir_ = mdir; } @@ -9568,23 +9595,9 @@ static int lfsr_mtree_pathlookup(lfs_t *lfs, const char *path, if (did_) { *did_ = did; } - if (name_) { - *name_ = name; - } - if (name_size_) { - *name_size_ = name_size; - } - // the root dir doesn't have an mdir really, so it's always - // a special case - return (mdir.mid == -1) - ? LFS_ERR_INVAL - : LFS_ERR_EXIST; + return 0; } - // found another name - name = path; - name_size = name_size__; - // only continue if we hit a directory if (tag != LFSR_TAG_DIR) { return (tag == LFSR_TAG_ORPHAN) @@ -9607,34 +9620,32 @@ static int lfsr_mtree_pathlookup(lfs_t *lfs, const char *path, } } + // update path as we parse + *path = path_; + // lookup up this name in the mtree - int err = lfsr_mtree_namelookup(lfs, did, name, name_size, + int err = lfsr_mtree_namelookup(lfs, did, path_, name_len, &mdir, &tag, NULL); - if (err) { - // report where to insert if we are the last name in our path - if (err == LFS_ERR_NOENT && lfs_strchr(name, '/') == NULL) { - if (mdir_) { - *mdir_ = mdir; - } - if (tag_) { - *tag_ = tag; - } - if (did_) { - *did_ = did; - } - if (name_) { - *name_ = name; - } - if (name_size_) { - *name_size_ = name_size; - } - return 0; - } + if (err && err != LFS_ERR_NOENT) { return err; } + // keep track of where to insert if we can't find path + if (err == LFS_ERR_NOENT) { + if (mdir_) { + *mdir_ = mdir; + } + if (tag_) { + *tag_ = tag; + } + if (did_) { + *did_ = did; + } + return LFS_ERR_NOENT; + } + // go on to next name - path += name_size; + path_ += name_len; next:; } } @@ -10357,26 +10368,24 @@ int lfsr_mkdir(lfs_t *lfs, const char *path) { } // lookup our parent + const char *path_ = path; lfsr_mdir_t mdir; lfsr_tag_t tag; lfsr_did_t did; - const char *name; - lfs_size_t name_size; - err = lfsr_mtree_pathlookup(lfs, path, - &mdir, &tag, - &did, &name, &name_size); - if (err && err != LFS_ERR_EXIST - && err != LFS_ERR_INVAL) { + err = lfsr_mtree_pathlookup(lfs, &path_, + &mdir, &tag, &did); + if (err && !(err == LFS_ERR_NOENT && lfsr_path_islast(path_))) { return err; } - // already exists? note orphans don't really exist - bool exists = (bool)err; + // already exists? orphans don't really exist + bool exists = (err != LFS_ERR_NOENT); if (exists && tag != LFSR_TAG_ORPHAN) { return LFS_ERR_EXIST; } // check that name fits - if (name_size > lfs->name_limit) { + lfs_size_t name_len = lfsr_path_namelen(path_); + if (name_len > lfs->name_limit) { return LFS_ERR_NAMETOOLONG; } @@ -10472,7 +10481,7 @@ int lfsr_mkdir(lfs_t *lfs, const char *path) { // committing our bookmark may have changed the mid of our metadata entry, // we need to look it up again, we can at least avoid the full path walk - err = lfsr_mtree_namelookup(lfs, did, name, name_size, + err = lfsr_mtree_namelookup(lfs, did, path_, name_len, &mdir, NULL, NULL); if (err && err != LFS_ERR_NOENT) { return err; @@ -10486,7 +10495,7 @@ int lfsr_mkdir(lfs_t *lfs, const char *path) { err = lfsr_mdir_commit(lfs, &mdir, LFSR_RATTRS( LFSR_RATTR_NAME( LFSR_TAG_SUP | LFSR_TAG_DIR, (!exists) ? +1 : 0, - did, name, name_size), + did, path_, name_len), LFSR_RATTR(LFSR_TAG_DID, 0, LFSR_DATA_LEB128(did_)))); if (err) { return err; @@ -10579,19 +10588,21 @@ int lfsr_remove(lfs_t *lfs, const char *path) { lfsr_mdir_t mdir; lfsr_tag_t tag; lfsr_did_t did; - const char *name; - lfs_size_t name_size; - err = lfsr_mtree_pathlookup(lfs, path, - &mdir, &tag, - &did, &name, &name_size); - if (err && err != LFS_ERR_EXIST) { + err = lfsr_mtree_pathlookup(lfs, &path, + &mdir, &tag, &did); + if (err) { return err; } - // doesn't exist? note orphans don't really exist - if (!err || tag == LFSR_TAG_ORPHAN) { + // orphans don't really exist + if (tag == LFSR_TAG_ORPHAN) { return LFS_ERR_NOENT; } + // trying to remove the root dir? + if (mdir.mid == -1) { + return LFS_ERR_INVAL; + } + // if we're removing a directory, we need to also remove the // bookmark entry lfsr_did_t did_ = 0; @@ -10629,7 +10640,7 @@ int lfsr_remove(lfs_t *lfs, const char *path) { (zombie) ? LFSR_RATTR_NAME( LFSR_TAG_SUP | LFSR_TAG_ORPHAN, 0, - did, name, name_size) + did, path, lfsr_path_namelen(path)) : LFSR_RATTR( LFSR_TAG_RM, -1, LFSR_DATA_NULL()))); if (err) { @@ -10696,41 +10707,53 @@ int lfsr_rename(lfs_t *lfs, const char *old_path, const char *new_path) { lfsr_mdir_t old_mdir; lfsr_tag_t old_tag; lfsr_did_t old_did; - err = lfsr_mtree_pathlookup(lfs, old_path, - &old_mdir, &old_tag, - &old_did, NULL, NULL); - if (err && err != LFS_ERR_EXIST) { + err = lfsr_mtree_pathlookup(lfs, &old_path, + &old_mdir, &old_tag, &old_did); + if (err) { return err; } - // doesn't exist? note orphans don't really exist - if (!err || old_tag == LFSR_TAG_ORPHAN) { + // orphans don't really exist + if (old_tag == LFSR_TAG_ORPHAN) { return LFS_ERR_NOENT; } + // trying to rename the root? + if (old_mdir.mid == -1) { + return LFS_ERR_INVAL; + } + // lookup new entry lfsr_mdir_t new_mdir; lfsr_tag_t new_tag; lfsr_did_t new_did; - const char *new_name; - lfs_size_t new_name_size; - err = lfsr_mtree_pathlookup(lfs, new_path, - &new_mdir, &new_tag, - &new_did, &new_name, &new_name_size); - if (err && err != LFS_ERR_EXIST) { + err = lfsr_mtree_pathlookup(lfs, &new_path, + &new_mdir, &new_tag, &new_did); + if (err && !(err == LFS_ERR_NOENT && lfsr_path_islast(new_path))) { return err; } // already exists? - bool exists = (err == LFS_ERR_EXIST); - lfsr_did_t new_did_ = 0; + bool exists = (err != LFS_ERR_NOENT); // there are a few cases we need to watch out for + lfs_size_t new_name_len = lfsr_path_namelen(new_path); + lfsr_did_t new_did_ = 0; if (!exists) { + // if we're a file, don't allow trailing slashes + if (old_tag != LFSR_TAG_DIR && lfsr_path_isdir(new_path)) { + return LFS_ERR_NOTDIR; + } + // check that name fits - if (new_name_size > lfs->name_limit) { + if (new_name_len > lfs->name_limit) { return LFS_ERR_NAMETOOLONG; } } else { + // trying to rename the root? + if (new_mdir.mid == -1) { + return LFS_ERR_INVAL; + } + // renaming different types is an error // // unless we found a orphan, these don't really exist @@ -10740,7 +10763,6 @@ int lfsr_rename(lfs_t *lfs, const char *old_path, const char *new_path) { : LFS_ERR_NOTDIR; } - // TODO is it? is this check necessary? // renaming to ourself is a noop if (old_mdir.mid == new_mdir.mid) { return 0; @@ -10780,7 +10802,7 @@ int lfsr_rename(lfs_t *lfs, const char *old_path, const char *new_path) { err = lfsr_mdir_commit(lfs, &new_mdir, LFSR_RATTRS( LFSR_RATTR_NAME( LFSR_TAG_SUP | old_tag, (!exists) ? +1 : 0, - new_did, new_name, new_name_size), + new_did, new_path, new_name_len), LFSR_RATTR_MOVE(LFSR_TAG_MOVE, 0, &old_mdir))); if (err) { return err; @@ -10897,22 +10919,18 @@ int lfsr_stat(lfs_t *lfs, const char *path, struct lfs_info *info) { // lookup our entry lfsr_mdir_t mdir; lfsr_tag_t tag; - const char *name; - lfs_size_t name_size; - int err = lfsr_mtree_pathlookup(lfs, path, - &mdir, &tag, - NULL, &name, &name_size); - if (err && err != LFS_ERR_EXIST - && err != LFS_ERR_INVAL) { + int err = lfsr_mtree_pathlookup(lfs, &path, + &mdir, &tag, NULL); + if (err) { return err; } - // doesn't exist? note orphans don't really exist - if (!err || tag == LFSR_TAG_ORPHAN) { + // orphans don't really exist + if (tag == LFSR_TAG_ORPHAN) { return LFS_ERR_NOENT; } // special case for root - if (err == LFS_ERR_INVAL) { + if (mdir.mid == -1) { lfs_strcpy(info->name, "/"); info->type = LFS_TYPE_DIR; info->size = 0; @@ -10921,7 +10939,7 @@ int lfsr_stat(lfs_t *lfs, const char *path, struct lfs_info *info) { // fill out our info struct return lfsr_stat_(lfs, &mdir, - tag, LFSR_DATA_BUF(name, name_size), + tag, LFSR_DATA_BUF(path, lfsr_path_namelen(path)), info); } @@ -10938,20 +10956,18 @@ int lfsr_dir_open(lfs_t *lfs, lfsr_dir_t *dir, const char *path) { // lookup our directory lfsr_mdir_t mdir; lfsr_tag_t tag; - int err = lfsr_mtree_pathlookup(lfs, path, - &mdir, &tag, - NULL, NULL, NULL); - if (err && err != LFS_ERR_EXIST - && err != LFS_ERR_INVAL) { + int err = lfsr_mtree_pathlookup(lfs, &path, + &mdir, &tag, NULL); + if (err) { return err; } - // doesn't exist? note orphans don't really exist - if (!err || tag == LFSR_TAG_ORPHAN) { + // orphans don't really exist + if (tag == LFSR_TAG_ORPHAN) { return LFS_ERR_NOENT; } // read our did from the mdir, unless we're root - if (err == LFS_ERR_INVAL) { + if (mdir.mid == -1) { dir->did = 0; } else { @@ -11156,14 +11172,13 @@ static int lfsr_lookupattr(lfs_t *lfs, const char *path, uint8_t type, lfsr_mdir_t *mdir_, lfsr_data_t *data_) { // lookup our entry lfsr_tag_t tag; - int err = lfsr_mtree_pathlookup(lfs, path, - mdir_, &tag, NULL, NULL, NULL); - if (err && err != LFS_ERR_EXIST - && err != LFS_ERR_INVAL) { + int err = lfsr_mtree_pathlookup(lfs, &path, + mdir_, &tag, NULL); + if (err) { return err; } - // doesn't exist? note orphans don't really exist - if (!err || tag == LFSR_TAG_ORPHAN) { + // orphans don't really exist + if (tag == LFSR_TAG_ORPHAN) { return LFS_ERR_NOENT; } @@ -11534,36 +11549,38 @@ int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file, // lookup our parent lfsr_tag_t tag; lfsr_did_t did; - const char *name; - lfs_size_t name_size; - int err = lfsr_mtree_pathlookup(lfs, path, - &file->o.o.mdir, &tag, - &did, &name, &name_size); - if (err && err != LFS_ERR_EXIST - && err != LFS_ERR_INVAL) { + int err = lfsr_mtree_pathlookup(lfs, &path, + &file->o.o.mdir, &tag, &did); + if (err && !(err == LFS_ERR_NOENT && lfsr_path_islast(path))) { return err; } // creating a new entry? - if (!err || tag == LFSR_TAG_ORPHAN) { + if (err == LFS_ERR_NOENT || tag == LFSR_TAG_ORPHAN) { if (!lfsr_o_iscreat(flags)) { return LFS_ERR_NOENT; } LFS_ASSERT(!lfsr_o_isrdonly(flags)); + // we're a file, don't allow trailing slashes + if (lfsr_path_isdir(path)) { + return LFS_ERR_NOTDIR; + } + // check that name fits - if (name_size > lfs->name_limit) { + lfs_size_t name_len = lfsr_path_namelen(path); + if (name_len > lfs->name_limit) { return LFS_ERR_NAMETOOLONG; } // create an orphan entry if we don't have one, this reserves the // mid until first sync - if (!err) { + if (err == LFS_ERR_NOENT) { lfs_alloc_ckpoint(lfs); err = lfsr_mdir_commit(lfs, &file->o.o.mdir, LFSR_RATTRS( LFSR_RATTR_NAME( LFSR_TAG_ORPHAN, +1, - did, name, name_size))); + did, path, name_len))); if (err) { return err; } diff --git a/tests/test_mount.toml b/tests/test_mount.toml index 2fbea650..75f08cff 100644 --- a/tests/test_mount.toml +++ b/tests/test_mount.toml @@ -925,17 +925,15 @@ code = ''' // change a file's type to something unknown lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; + const char *path = "b"; lfsr_mdir_t mdir; lfsr_did_t did; - const char *name; - lfs_size_t name_size; - lfsr_mtree_pathlookup(&lfs, "b", - &mdir, NULL, - &did, &name, &name_size) => LFS_ERR_EXIST; + lfsr_mtree_pathlookup(&lfs, &path, + &mdir, NULL, &did) => 0; lfsr_mdir_commit(&lfs, &mdir, LFSR_RATTRS( LFSR_RATTR_NAME( LFSR_TAG_SUB | (LFSR_TAG_NAME + 0x13), 0, - did, name, name_size))) => 0; + did, path, lfsr_path_namelen(path)))) => 0; lfsr_unmount(&lfs) => 0; // mount should now fail diff --git a/tests/test_paths.toml b/tests/test_paths.toml index 6a230183..08ef3b3e 100644 --- a/tests/test_paths.toml +++ b/tests/test_paths.toml @@ -2,325 +2,7398 @@ after = 'test_dirs' # simple path test -[cases.test_paths_normal] +[cases.test_paths_simple] +defines.DIR = [false, true] code = ''' lfs_t lfs; lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; - lfsr_mkdir(&lfs, "tea") => 0; - lfsr_mkdir(&lfs, "tea/green") => 0; - lfsr_mkdir(&lfs, "tea/oolong") => 0; - lfsr_mkdir(&lfs, "tea/black") => 0; + lfsr_mount(&lfs, LFS_F_RDWR, CFG) => 0; + // create paths + lfsr_mkdir(&lfs, "coffee") => 0; + if (DIR) { + lfsr_mkdir(&lfs, "coffee/drip") => 0; + lfsr_mkdir(&lfs, "coffee/coldbrew") => 0; + lfsr_mkdir(&lfs, "coffee/turkish") => 0; + lfsr_mkdir(&lfs, "coffee/tubruk") => 0; + lfsr_mkdir(&lfs, "coffee/vietnamese") => 0; + lfsr_mkdir(&lfs, "coffee/thai") => 0; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + } + + // stat paths struct lfs_info info; - lfsr_stat(&lfs, "tea/green", &info) => 0; - assert(strcmp(info.name, "green") == 0); - lfsr_stat(&lfs, "/tea/green", &info) => 0; - assert(strcmp(info.name, "green") == 0); + lfsr_stat(&lfs, "coffee/drip", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/coldbrew", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/turkish", &info) => 0; + assert(strcmp(info.name, "turkish") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/tubruk", &info) => 0; + assert(strcmp(info.name, "tubruk") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/vietnamese", &info) => 0; + assert(strcmp(info.name, "vietnamese") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/thai", &info) => 0; + assert(strcmp(info.name, "thai") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + // file open paths, only works on files! + if (DIR) { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "coffee/drip", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/turkish", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/tubruk", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/vietnamese", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/thai", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + + lfsr_file_open(&lfs, &file, "coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfsr_file_open(&lfs, &file, "coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "coffee/drip", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/turkish", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/tubruk", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/vietnamese", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/thai", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + + lfsr_file_open(&lfs, &file, "coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + + lfsr_file_open(&lfs, &file, "coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + } + + // dir open paths, only works on dirs! + if (DIR) { + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "coffee/drip") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "coffee/coldbrew") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "coffee/turkish") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "coffee/tubruk") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "coffee/vietnamese") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "coffee/thai") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + } else { + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "coffee/drip") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "coffee/coldbrew") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "coffee/turkish") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "coffee/tubruk") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "coffee/vietnamese") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "coffee/thai") => LFS_ERR_NOTDIR; + } + + // rename paths + lfsr_mkdir(&lfs, "espresso") => 0; + lfsr_rename(&lfs, + "coffee/drip", + "espresso/espresso") => 0; + lfsr_rename(&lfs, + "coffee/coldbrew", + "espresso/americano") => 0; + lfsr_rename(&lfs, + "coffee/turkish", + "espresso/macchiato") => 0; + lfsr_rename(&lfs, + "coffee/tubruk", + "espresso/latte") => 0; + lfsr_rename(&lfs, + "coffee/vietnamese", + "espresso/cappuccino") => 0; + lfsr_rename(&lfs, + "coffee/thai", + "espresso/mocha") => 0; + + // stat paths + lfsr_stat(&lfs, "espresso/espresso", &info) => 0; + assert(strcmp(info.name, "espresso") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "espresso/americano", &info) => 0; + assert(strcmp(info.name, "americano") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "espresso/macchiato", &info) => 0; + assert(strcmp(info.name, "macchiato") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "espresso/latte", &info) => 0; + assert(strcmp(info.name, "latte") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "espresso/cappuccino", &info) => 0; + assert(strcmp(info.name, "cappuccino") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "espresso/mocha", &info) => 0; + assert(strcmp(info.name, "mocha") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfsr_stat(&lfs, "coffee/drip", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/coldbrew", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/turkish", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/tubruk", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/vietnamese", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/thai", &info) => LFS_ERR_NOENT; + + // remove paths + lfsr_remove(&lfs, "espresso/espresso") => 0; + lfsr_remove(&lfs, "espresso/americano") => 0; + lfsr_remove(&lfs, "espresso/macchiato") => 0; + lfsr_remove(&lfs, "espresso/latte") => 0; + lfsr_remove(&lfs, "espresso/cappuccino") => 0; + lfsr_remove(&lfs, "espresso/mocha") => 0; + + // stat paths + lfsr_stat(&lfs, "espresso/espresso", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/americano", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/macchiato", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/latte", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/cappuccino", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/mocha", &info) => LFS_ERR_NOENT; + + lfsr_unmount(&lfs) => 0; +''' + +# absolute path test +# +# littlefs does not provide cd, so these are the same as relative paths +[cases.test_paths_absolute] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; + lfsr_mount(&lfs, LFS_F_RDWR, CFG) => 0; + + // create paths + lfsr_mkdir(&lfs, "coffee") => 0; + if (DIR) { + lfsr_mkdir(&lfs, "/coffee/drip") => 0; + lfsr_mkdir(&lfs, "/coffee/coldbrew") => 0; + lfsr_mkdir(&lfs, "/coffee/turkish") => 0; + lfsr_mkdir(&lfs, "/coffee/tubruk") => 0; + lfsr_mkdir(&lfs, "/coffee/vietnamese") => 0; + lfsr_mkdir(&lfs, "/coffee/thai") => 0; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + } + + // stat paths + struct lfs_info info; + lfsr_stat(&lfs, "/coffee/drip", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/coldbrew", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/coffee/turkish", &info) => 0; + assert(strcmp(info.name, "turkish") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/tubruk", &info) => 0; + assert(strcmp(info.name, "tubruk") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/coffee/vietnamese", &info) => 0; + assert(strcmp(info.name, "vietnamese") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/thai", &info) => 0; + assert(strcmp(info.name, "thai") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + // file open paths, only works on files! + if (DIR) { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "/coffee/drip", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/coffee/coldbrew", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/coffee/turkish", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/coffee/tubruk", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/coffee/vietnamese", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/coffee/thai", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + + lfsr_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfsr_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "/coffee/drip", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/coldbrew", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/turkish", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/tubruk", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/vietnamese", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/thai", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + + lfsr_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + + lfsr_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + } + + // dir open paths, only works on dirs! + if (DIR) { + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "/coffee/drip") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "/coffee/coldbrew") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "/coffee/turkish") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "/coffee/tubruk") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "/coffee/vietnamese") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "/coffee/thai") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + } else { + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "/coffee/drip") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "/coffee/coldbrew") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "/coffee/turkish") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "/coffee/tubruk") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "/coffee/vietnamese") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "/coffee/thai") => LFS_ERR_NOTDIR; + } + + // rename paths + lfsr_mkdir(&lfs, "espresso") => 0; + lfsr_rename(&lfs, + "coffee/drip", + "/espresso/espresso") => 0; + lfsr_rename(&lfs, + "coffee/coldbrew", + "/espresso/americano") => 0; + lfsr_rename(&lfs, + "/coffee/turkish", + "espresso/macchiato") => 0; + lfsr_rename(&lfs, + "/coffee/tubruk", + "espresso/latte") => 0; + lfsr_rename(&lfs, + "/coffee/vietnamese", + "/espresso/cappuccino") => 0; + lfsr_rename(&lfs, + "/coffee/thai", + "/espresso/mocha") => 0; + + // stat paths + lfsr_stat(&lfs, "/espresso/espresso", &info) => 0; + assert(strcmp(info.name, "espresso") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "espresso/americano", &info) => 0; + assert(strcmp(info.name, "americano") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/espresso/macchiato", &info) => 0; + assert(strcmp(info.name, "macchiato") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "espresso/latte", &info) => 0; + assert(strcmp(info.name, "latte") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/espresso/cappuccino", &info) => 0; + assert(strcmp(info.name, "cappuccino") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "espresso/mocha", &info) => 0; + assert(strcmp(info.name, "mocha") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfsr_stat(&lfs, "/coffee/drip", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/coffee/coldbrew", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/coffee/turkish", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/coffee/tubruk", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/coffee/vietnamese", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/coffee/thai", &info) => LFS_ERR_NOENT; + + // remove paths + lfsr_remove(&lfs, "/espresso/espresso") => 0; + lfsr_remove(&lfs, "/espresso/americano") => 0; + lfsr_remove(&lfs, "/espresso/macchiato") => 0; + lfsr_remove(&lfs, "/espresso/latte") => 0; + lfsr_remove(&lfs, "/espresso/cappuccino") => 0; + lfsr_remove(&lfs, "/espresso/mocha") => 0; + + // stat paths + lfsr_stat(&lfs, "/espresso/espresso", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/americano", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/espresso/macchiato", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/latte", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/espresso/cappuccino", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/mocha", &info) => LFS_ERR_NOENT; - lfsr_mkdir(&lfs, "/milk") => 0; - lfsr_stat(&lfs, "/milk", &info) => 0; - assert(strcmp(info.name, "milk") == 0); - lfsr_stat(&lfs, "milk", &info) => 0; - assert(strcmp(info.name, "milk") == 0); lfsr_unmount(&lfs) => 0; ''' # redundant slashes [cases.test_paths_redundant_slashes] +defines.DIR = [false, true] code = ''' lfs_t lfs; lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; - lfsr_mkdir(&lfs, "tea") => 0; - lfsr_mkdir(&lfs, "tea/green") => 0; - lfsr_mkdir(&lfs, "tea/oolong") => 0; - lfsr_mkdir(&lfs, "tea/black") => 0; + lfsr_mount(&lfs, LFS_F_RDWR, CFG) => 0; - struct lfs_info info; - lfsr_stat(&lfs, "/tea/green", &info) => 0; - assert(strcmp(info.name, "green") == 0); - lfsr_stat(&lfs, "//tea//green", &info) => 0; - assert(strcmp(info.name, "green") == 0); - lfsr_stat(&lfs, "///tea///green", &info) => 0; - assert(strcmp(info.name, "green") == 0); - - lfsr_mkdir(&lfs, "////milk") => 0; - lfsr_stat(&lfs, "////milk", &info) => 0; - assert(strcmp(info.name, "milk") == 0); - lfsr_stat(&lfs, "milk", &info) => 0; - assert(strcmp(info.name, "milk") == 0); - lfsr_unmount(&lfs) => 0; -''' - -# dot path test -[cases.test_paths_dot] -code = ''' - lfs_t lfs; - lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; - lfsr_mkdir(&lfs, "tea") => 0; - lfsr_mkdir(&lfs, "tea/green") => 0; - lfsr_mkdir(&lfs, "tea/oolong") => 0; - lfsr_mkdir(&lfs, "tea/black") => 0; - - struct lfs_info info; - lfsr_stat(&lfs, "./tea/green", &info) => 0; - assert(strcmp(info.name, "green") == 0); - lfsr_stat(&lfs, "/./tea/green", &info) => 0; - assert(strcmp(info.name, "green") == 0); - lfsr_stat(&lfs, "/././tea/green", &info) => 0; - assert(strcmp(info.name, "green") == 0); - lfsr_stat(&lfs, "/./tea/./green", &info) => 0; - assert(strcmp(info.name, "green") == 0); - - lfsr_mkdir(&lfs, "/./milk") => 0; - lfsr_stat(&lfs, "/./milk", &info) => 0; - assert(strcmp(info.name, "milk") == 0); - lfsr_stat(&lfs, "milk", &info) => 0; - assert(strcmp(info.name, "milk") == 0); - lfsr_unmount(&lfs) => 0; -''' - -# dot dot path test -[cases.test_paths_dot_dot] -code = ''' - lfs_t lfs; - lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; - lfsr_mkdir(&lfs, "tea") => 0; - lfsr_mkdir(&lfs, "tea/green") => 0; - lfsr_mkdir(&lfs, "tea/oolong") => 0; - lfsr_mkdir(&lfs, "tea/black") => 0; + // create paths lfsr_mkdir(&lfs, "coffee") => 0; - lfsr_mkdir(&lfs, "coffee/drip") => 0; - lfsr_mkdir(&lfs, "coffee/espresso") => 0; - lfsr_mkdir(&lfs, "coffee/coldbrew") => 0; + if (DIR) { + lfsr_mkdir(&lfs, "/coffee/drip") => 0; + lfsr_mkdir(&lfs, "//coffee//coldbrew") => 0; + lfsr_mkdir(&lfs, "///coffee///turkish") => 0; + lfsr_mkdir(&lfs, "////coffee////tubruk") => 0; + lfsr_mkdir(&lfs, "/////coffee/////vietnamese") => 0; + lfsr_mkdir(&lfs, "//////coffee//////thai") => 0; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "//coffee//coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "///coffee///turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "////coffee////tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/////coffee/////vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "//////coffee//////thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + } + // stat paths struct lfs_info info; - lfsr_stat(&lfs, "coffee/../tea/green", &info) => 0; - assert(strcmp(info.name, "green") == 0); - lfsr_stat(&lfs, "tea/black/../green", &info) => 0; - assert(strcmp(info.name, "green") == 0); - lfsr_stat(&lfs, "coffee/coldbrew/../../tea/green", &info) => 0; - assert(strcmp(info.name, "green") == 0); - lfsr_stat(&lfs, "coffee/../coffee/../tea/green", &info) => 0; - assert(strcmp(info.name, "green") == 0); + lfsr_stat(&lfs, "//////coffee//////drip", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/////coffee/////coldbrew", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "////coffee////turkish", &info) => 0; + assert(strcmp(info.name, "turkish") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "///coffee///tubruk", &info) => 0; + assert(strcmp(info.name, "tubruk") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "//coffee//vietnamese", &info) => 0; + assert(strcmp(info.name, "vietnamese") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/coffee/thai", &info) => 0; + assert(strcmp(info.name, "thai") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + // file open paths, only works on files! + if (DIR) { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "/coffee/drip", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "//coffee//coldbrew", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "///coffee///turkish", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "////coffee////tubruk", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/////coffee/////vietnamese", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "//////coffee//////thai", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + + lfsr_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "//coffee//coldbrew", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "///coffee///turkish", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "////coffee////tubruk", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/////coffee/////vietnamese", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "//////coffee//////thai", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfsr_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "//coffee//coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "///coffee///turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "////coffee////tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/////coffee/////vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "//////coffee//////thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "/coffee/drip", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "//coffee//coldbrew", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "///coffee///turkish", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "////coffee////tubruk", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/////coffee/////vietnamese", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "//////coffee//////thai", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + + lfsr_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "//coffee//coldbrew", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "///coffee///turkish", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "////coffee////tubruk", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/////coffee/////vietnamese", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "//////coffee//////thai", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + + lfsr_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "//coffee//coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "///coffee///turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "////coffee////tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/////coffee/////vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "//////coffee//////thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + } + + // dir open paths, only works on dirs! + if (DIR) { + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "/coffee/drip") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "//coffee//coldbrew") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "///coffee///turkish") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "////coffee////tubruk") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "/////coffee/////vietnamese") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "//////coffee//////thai") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + } else { + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "/coffee/drip") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "//coffee//coldbrew") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "///coffee///turkish") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "////coffee////tubruk") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "/////coffee/////vietnamese") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "//////coffee//////thai") => LFS_ERR_NOTDIR; + } + + // rename paths + lfsr_mkdir(&lfs, "espresso") => 0; + lfsr_rename(&lfs, + "//////coffee//////drip", + "/espresso/espresso") => 0; + lfsr_rename(&lfs, + "/////coffee/////coldbrew", + "//espresso//americano") => 0; + lfsr_rename(&lfs, + "////coffee////turkish", + "///espresso///macchiato") => 0; + lfsr_rename(&lfs, + "///coffee///tubruk", + "////espresso////latte") => 0; + lfsr_rename(&lfs, + "//coffee//vietnamese", + "/////espresso/////cappuccino") => 0; + lfsr_rename(&lfs, + "/coffee/thai", + "//////espresso//////mocha") => 0; + + // stat paths + lfsr_stat(&lfs, "//////espresso//////espresso", &info) => 0; + assert(strcmp(info.name, "espresso") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/////espresso/////americano", &info) => 0; + assert(strcmp(info.name, "americano") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "////espresso////macchiato", &info) => 0; + assert(strcmp(info.name, "macchiato") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "///espresso///latte", &info) => 0; + assert(strcmp(info.name, "latte") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "//espresso//cappuccino", &info) => 0; + assert(strcmp(info.name, "cappuccino") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/espresso/mocha", &info) => 0; + assert(strcmp(info.name, "mocha") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfsr_stat(&lfs, "//////coffee//////drip", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/////coffee/////coldbrew", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "////coffee////turkish", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "///coffee///tubruk", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "//coffee//vietnamese", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/coffee/thai", &info) => LFS_ERR_NOENT; + + // remove paths + lfsr_remove(&lfs, "/espresso/espresso") => 0; + lfsr_remove(&lfs, "//espresso//americano") => 0; + lfsr_remove(&lfs, "///espresso///macchiato") => 0; + lfsr_remove(&lfs, "////espresso////latte") => 0; + lfsr_remove(&lfs, "/////espresso/////cappuccino") => 0; + lfsr_remove(&lfs, "//////espresso//////mocha") => 0; + + // stat paths + lfsr_stat(&lfs, "//////espresso//////espresso", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/////espresso/////americano", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "////espresso////macchiato", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "///espresso///latte", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "//espresso//cappuccino", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/espresso/mocha", &info) => LFS_ERR_NOENT; - lfsr_mkdir(&lfs, "coffee/../milk") => 0; - lfsr_stat(&lfs, "coffee/../milk", &info) => 0; - strcmp(info.name, "milk") => 0; - lfsr_stat(&lfs, "milk", &info) => 0; - strcmp(info.name, "milk") => 0; lfsr_unmount(&lfs) => 0; ''' -# trailing dot path test -[cases.test_paths_trailing_dot] +# test trailing slashes +# +# trailing slashes are only allowed on directories +[cases.test_paths_trailing_slashes] +defines.DIR = [false, true] code = ''' lfs_t lfs; lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; - lfsr_mkdir(&lfs, "tea") => 0; - lfsr_mkdir(&lfs, "tea/green") => 0; - lfsr_mkdir(&lfs, "tea/oolong") => 0; - lfsr_mkdir(&lfs, "tea/black") => 0; + lfsr_mount(&lfs, LFS_F_RDWR, CFG) => 0; + // create paths + lfsr_mkdir(&lfs, "coffee") => 0; + if (DIR) { + lfsr_mkdir(&lfs, "coffee/drip/") => 0; + lfsr_mkdir(&lfs, "coffee/coldbrew//") => 0; + lfsr_mkdir(&lfs, "coffee/turkish///") => 0; + lfsr_mkdir(&lfs, "coffee/tubruk////") => 0; + lfsr_mkdir(&lfs, "coffee/vietnamese/////") => 0; + lfsr_mkdir(&lfs, "coffee/thai//////") => 0; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "coffee/drip/", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/coldbrew//", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/turkish///", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/tubruk////", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/vietnamese/////", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/thai//////", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + + // still create so we have something to test + lfsr_file_open(&lfs, &file, "coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + } + + // stat paths struct lfs_info info; - lfsr_stat(&lfs, "tea/green/", &info) => 0; - assert(strcmp(info.name, "green") == 0); - lfsr_stat(&lfs, "tea/green/.", &info) => 0; - assert(strcmp(info.name, "green") == 0); - lfsr_stat(&lfs, "tea/green/./.", &info) => 0; - assert(strcmp(info.name, "green") == 0); - lfsr_stat(&lfs, "tea/green/..", &info) => 0; - assert(strcmp(info.name, "tea") == 0); - lfsr_stat(&lfs, "tea/green/../.", &info) => 0; - assert(strcmp(info.name, "tea") == 0); + if (DIR) { + lfsr_stat(&lfs, "coffee/drip//////", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == LFS_TYPE_DIR); + lfsr_stat(&lfs, "coffee/coldbrew/////", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); + assert(info.type == LFS_TYPE_DIR); + lfsr_stat(&lfs, "coffee/turkish////", &info) => 0; + assert(strcmp(info.name, "turkish") == 0); + assert(info.type == LFS_TYPE_DIR); + lfsr_stat(&lfs, "coffee/tubruk///", &info) => 0; + assert(strcmp(info.name, "tubruk") == 0); + assert(info.type == LFS_TYPE_DIR); + lfsr_stat(&lfs, "coffee/vietnamese//", &info) => 0; + assert(strcmp(info.name, "vietnamese") == 0); + assert(info.type == LFS_TYPE_DIR); + lfsr_stat(&lfs, "coffee/thai/", &info) => 0; + assert(strcmp(info.name, "thai") == 0); + assert(info.type == LFS_TYPE_DIR); + } else { + lfsr_stat(&lfs, "coffee/drip//////", &info) => LFS_ERR_NOTDIR; + lfsr_stat(&lfs, "coffee/coldbrew/////", &info) => LFS_ERR_NOTDIR; + lfsr_stat(&lfs, "coffee/turkish////", &info) => LFS_ERR_NOTDIR; + lfsr_stat(&lfs, "coffee/tubruk///", &info) => LFS_ERR_NOTDIR; + lfsr_stat(&lfs, "coffee/vietnamese//", &info) => LFS_ERR_NOTDIR; + lfsr_stat(&lfs, "coffee/thai/", &info) => LFS_ERR_NOTDIR; + } + + // file open paths, only works on files! + if (DIR) { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "coffee/drip/", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/coldbrew//", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/turkish///", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/tubruk////", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/vietnamese/////", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/thai//////", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + + lfsr_file_open(&lfs, &file, "coffee/drip/", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/coldbrew//", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/turkish///", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/tubruk////", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/vietnamese/////", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/thai//////", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfsr_file_open(&lfs, &file, "coffee/drip/", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "coffee/coldbrew//", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "coffee/turkish///", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "coffee/tubruk////", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "coffee/vietnamese/////", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "coffee/thai//////", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "coffee/drip/", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/coldbrew//", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/turkish///", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/tubruk////", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/vietnamese/////", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/thai//////", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + + lfsr_file_open(&lfs, &file, "coffee/drip/", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/coldbrew//", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/turkish///", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/tubruk////", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/vietnamese/////", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/thai//////", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + + lfsr_file_open(&lfs, &file, "coffee/drip/", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/coldbrew//", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/turkish///", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/tubruk////", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/vietnamese/////", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/thai//////", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + } + + // dir open paths, only works on dirs! + if (DIR) { + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "coffee/drip/") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "coffee/coldbrew//") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "coffee/turkish///") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "coffee/tubruk////") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "coffee/vietnamese/////") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "coffee/thai//////") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + } else { + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "coffee/drip/") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "coffee/coldbrew//") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "coffee/turkish///") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "coffee/tubruk////") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "coffee/vietnamese/////") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "coffee/thai//////") => LFS_ERR_NOTDIR; + } + + // rename paths + lfsr_mkdir(&lfs, "espresso") => 0; + if (DIR) { + lfsr_rename(&lfs, + "coffee/drip//////", + "espresso/espresso/") => 0; + lfsr_rename(&lfs, + "coffee/coldbrew/////", + "espresso/americano//") => 0; + lfsr_rename(&lfs, + "coffee/turkish////", + "espresso/macchiato///") => 0; + lfsr_rename(&lfs, + "coffee/tubruk///", + "espresso/latte////") => 0; + lfsr_rename(&lfs, + "coffee/vietnamese//", + "espresso/cappuccino/////") => 0; + lfsr_rename(&lfs, + "coffee/thai/", + "espresso/mocha//////") => 0; + + // stat paths + lfsr_stat(&lfs, "espresso/espresso//////", &info) => 0; + assert(strcmp(info.name, "espresso") == 0); + assert(info.type == LFS_TYPE_DIR); + lfsr_stat(&lfs, "espresso/americano/////", &info) => 0; + assert(strcmp(info.name, "americano") == 0); + assert(info.type == LFS_TYPE_DIR); + lfsr_stat(&lfs, "espresso/macchiato////", &info) => 0; + assert(strcmp(info.name, "macchiato") == 0); + assert(info.type == LFS_TYPE_DIR); + lfsr_stat(&lfs, "espresso/latte///", &info) => 0; + assert(strcmp(info.name, "latte") == 0); + assert(info.type == LFS_TYPE_DIR); + lfsr_stat(&lfs, "espresso/cappuccino//", &info) => 0; + assert(strcmp(info.name, "cappuccino") == 0); + assert(info.type == LFS_TYPE_DIR); + lfsr_stat(&lfs, "espresso/mocha/", &info) => 0; + assert(strcmp(info.name, "mocha") == 0); + assert(info.type == LFS_TYPE_DIR); + + lfsr_stat(&lfs, "coffee/drip//////", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/coldbrew/////", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/turkish////", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/tubruk///", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/vietnamese//", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/thai/", &info) => LFS_ERR_NOENT; + + // remove paths + lfsr_remove(&lfs, "espresso/espresso/") => 0; + lfsr_remove(&lfs, "espresso/americano//") => 0; + lfsr_remove(&lfs, "espresso/macchiato///") => 0; + lfsr_remove(&lfs, "espresso/latte////") => 0; + lfsr_remove(&lfs, "espresso/cappuccino/////") => 0; + lfsr_remove(&lfs, "espresso/mocha//////") => 0; + + // stat paths + lfsr_stat(&lfs, "espresso/espresso//////", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/americano/////", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/macchiato////", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/latte///", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/cappuccino//", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/mocha/", &info) => LFS_ERR_NOENT; + + } else { + // bad source + lfsr_rename(&lfs, + "coffee/drip//////", + "espresso/espresso") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "coffee/coldbrew/////", + "espresso/americano") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "coffee/turkish////", + "espresso/macchiato") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "coffee/tubruk///", + "espresso/latte") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "coffee/vietnamese//", + "espresso/cappuccino") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "coffee/thai/", + "espresso/mocha") => LFS_ERR_NOTDIR; + + // bad destination + lfsr_rename(&lfs, + "coffee/drip", + "espresso/espresso/") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "coffee/coldbrew", + "espresso/americano//") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "coffee/turkish", + "espresso/macchiato///") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "coffee/tubruk", + "espresso/latte////") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "coffee/vietnamese", + "espresso/cappuccino/////") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "coffee/thai", + "espresso/mocha//////") => LFS_ERR_NOTDIR; + + // bad source and bad destination + lfsr_rename(&lfs, + "coffee/drip//////", + "espresso/espresso/") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "coffee/coldbrew/////", + "espresso/americano//") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "coffee/turkish////", + "espresso/macchiato///") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "coffee/tubruk///", + "espresso/latte////") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "coffee/vietnamese//", + "espresso/cappuccino/////") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "coffee/thai/", + "espresso/mocha//////") => LFS_ERR_NOTDIR; + + // remove paths + lfsr_remove(&lfs, "coffee/drip/") => LFS_ERR_NOTDIR; + lfsr_remove(&lfs, "coffee/coldbrew//") => LFS_ERR_NOTDIR; + lfsr_remove(&lfs, "coffee/turkish///") => LFS_ERR_NOTDIR; + lfsr_remove(&lfs, "coffee/tubruk////") => LFS_ERR_NOTDIR; + lfsr_remove(&lfs, "coffee/vietnamese/////") => LFS_ERR_NOTDIR; + lfsr_remove(&lfs, "coffee/thai//////") => LFS_ERR_NOTDIR; + + // stat paths + lfsr_stat(&lfs, "espresso/espresso", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/americano", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/macchiato", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/latte", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/cappuccino", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/mocha", &info) => LFS_ERR_NOENT; + + lfsr_stat(&lfs, "coffee/drip", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == LFS_TYPE_REG); + lfsr_stat(&lfs, "coffee/coldbrew", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); + assert(info.type == LFS_TYPE_REG); + lfsr_stat(&lfs, "coffee/turkish", &info) => 0; + assert(strcmp(info.name, "turkish") == 0); + assert(info.type == LFS_TYPE_REG); + lfsr_stat(&lfs, "coffee/tubruk", &info) => 0; + assert(strcmp(info.name, "tubruk") == 0); + assert(info.type == LFS_TYPE_REG); + lfsr_stat(&lfs, "coffee/vietnamese", &info) => 0; + assert(strcmp(info.name, "vietnamese") == 0); + assert(info.type == LFS_TYPE_REG); + lfsr_stat(&lfs, "coffee/thai", &info) => 0; + assert(strcmp(info.name, "thai") == 0); + assert(info.type == LFS_TYPE_REG); + } + + lfsr_unmount(&lfs) => 0; +''' + +# dot path tests +[cases.test_paths_dots] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; + lfsr_mount(&lfs, LFS_F_RDWR, CFG) => 0; + + // create paths + lfsr_mkdir(&lfs, "coffee") => 0; + if (DIR) { + lfsr_mkdir(&lfs, "/coffee/drip") => 0; + lfsr_mkdir(&lfs, "/./coffee/./coldbrew") => 0; + lfsr_mkdir(&lfs, "/././coffee/././turkish") => 0; + lfsr_mkdir(&lfs, "/./././coffee/./././tubruk") => 0; + lfsr_mkdir(&lfs, "/././././coffee/././././vietnamese") => 0; + lfsr_mkdir(&lfs, "/./././././coffee/./././././thai") => 0; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/./coffee/./coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/././coffee/././turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/./././coffee/./././tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/././././coffee/././././vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/./././././coffee/./././././thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + } + + // stat paths + struct lfs_info info; + lfsr_stat(&lfs, "/./././././coffee/./././././drip", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/././././coffee/././././coldbrew", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/./././coffee/./././turkish", &info) => 0; + assert(strcmp(info.name, "turkish") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/././coffee/././tubruk", &info) => 0; + assert(strcmp(info.name, "tubruk") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/./coffee/./vietnamese", &info) => 0; + assert(strcmp(info.name, "vietnamese") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/coffee/thai", &info) => 0; + assert(strcmp(info.name, "thai") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + // file open paths, only works on files! + if (DIR) { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "/coffee/drip", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/./coffee/./coldbrew", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/././coffee/././turkish", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/./././coffee/./././tubruk", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/././././coffee/././././vietnamese", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/./././././coffee/./././././thai", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + + lfsr_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/./coffee/./coldbrew", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/././coffee/././turkish", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/./././coffee/./././tubruk", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/././././coffee/././././vietnamese", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/./././././coffee/./././././thai", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfsr_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/./coffee/./coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/././coffee/././turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/./././coffee/./././tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/././././coffee/././././vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/./././././coffee/./././././thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "/coffee/drip", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/./coffee/./coldbrew", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/././coffee/././turkish", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/./././coffee/./././tubruk", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/././././coffee/././././vietnamese", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/./././././coffee/./././././thai", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + + lfsr_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/./coffee/./coldbrew", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/././coffee/././turkish", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/./././coffee/./././tubruk", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/././././coffee/././././vietnamese", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/./././././coffee/./././././thai", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + + lfsr_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/./coffee/./coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/././coffee/././turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/./././coffee/./././tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/././././coffee/././././vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/./././././coffee/./././././thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + } + + // dir open paths, only works on dirs! + if (DIR) { + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "/coffee/drip") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "/./coffee/./coldbrew") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "/././coffee/././turkish") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "/./././coffee/./././tubruk") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "/././././coffee/././././vietnamese") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "/./././././coffee/./././././thai") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + } else { + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "/coffee/drip") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "/./coffee/./coldbrew") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "/././coffee/././turkish") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "/./././coffee/./././tubruk") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "/././././coffee/././././vietnamese") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "/./././././coffee/./././././thai") => LFS_ERR_NOTDIR; + } + + // rename paths + lfsr_mkdir(&lfs, "espresso") => 0; + lfsr_rename(&lfs, + "/./././././coffee/./././././drip", + "/espresso/espresso") => 0; + lfsr_rename(&lfs, + "/././././coffee/././././coldbrew", + "/./espresso/./americano") => 0; + lfsr_rename(&lfs, + "/./././coffee/./././turkish", + "/././espresso/././macchiato") => 0; + lfsr_rename(&lfs, + "/././coffee/././tubruk", + "/./././espresso/./././latte") => 0; + lfsr_rename(&lfs, + "/./coffee/./vietnamese", + "/././././espresso/././././cappuccino") => 0; + lfsr_rename(&lfs, + "/coffee/thai", + "/./././././espresso/./././././mocha") => 0; + + // stat paths + lfsr_stat(&lfs, "/./././././espresso/./././././espresso", &info) => 0; + assert(strcmp(info.name, "espresso") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/././././espresso/././././americano", &info) => 0; + assert(strcmp(info.name, "americano") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/./././espresso/./././macchiato", &info) => 0; + assert(strcmp(info.name, "macchiato") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/././espresso/././latte", &info) => 0; + assert(strcmp(info.name, "latte") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/./espresso/./cappuccino", &info) => 0; + assert(strcmp(info.name, "cappuccino") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/espresso/mocha", &info) => 0; + assert(strcmp(info.name, "mocha") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfsr_stat(&lfs, "/./././././coffee/./././././drip", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/././././coffee/././././coldbrew", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/./././coffee/./././turkish", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/././coffee/././tubruk", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/./coffee/./vietnamese", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/coffee/thai", &info) => LFS_ERR_NOENT; + + // remove paths + lfsr_remove(&lfs, "/espresso/espresso") => 0; + lfsr_remove(&lfs, "/./espresso/./americano") => 0; + lfsr_remove(&lfs, "/././espresso/././macchiato") => 0; + lfsr_remove(&lfs, "/./././espresso/./././latte") => 0; + lfsr_remove(&lfs, "/././././espresso/././././cappuccino") => 0; + lfsr_remove(&lfs, "/./././././espresso/./././././mocha") => 0; + + // stat paths + lfsr_stat(&lfs, "/./././././espresso/./././././espresso", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/././././espresso/././././americano", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/./././espresso/./././macchiato", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/././espresso/././latte", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/./espresso/./cappuccino", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/espresso/mocha", &info) => LFS_ERR_NOENT; + + lfsr_unmount(&lfs) => 0; +''' + +# test trailing dots, these get a bit weird +# +# POSIX deviations: +# +# - We accept modifications of directories with trailing dots: +# - littlefs: remove("a/.") => 0 +# - POSIX: remove("a/.") => EBUSY +# Reason: Not worth implementing. +# +[cases.test_paths_trailing_dots] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; + lfsr_mount(&lfs, LFS_F_RDWR, CFG) => 0; + + // create paths + lfsr_mkdir(&lfs, "coffee") => 0; + if (DIR) { + lfsr_mkdir(&lfs, "coffee/drip/.") => LFS_ERR_NOENT; + lfsr_mkdir(&lfs, "coffee/coldbrew/./.") => LFS_ERR_NOENT; + lfsr_mkdir(&lfs, "coffee/turkish/././.") => LFS_ERR_NOENT; + lfsr_mkdir(&lfs, "coffee/tubruk/./././.") => LFS_ERR_NOENT; + lfsr_mkdir(&lfs, "coffee/vietnamese/././././.") => LFS_ERR_NOENT; + lfsr_mkdir(&lfs, "coffee/thai/./././././.") => LFS_ERR_NOENT; + + // still create so we have something to test + lfsr_mkdir(&lfs, "coffee/drip") => 0; + lfsr_mkdir(&lfs, "coffee/coldbrew") => 0; + lfsr_mkdir(&lfs, "coffee/turkish") => 0; + lfsr_mkdir(&lfs, "coffee/tubruk") => 0; + lfsr_mkdir(&lfs, "coffee/vietnamese") => 0; + lfsr_mkdir(&lfs, "coffee/thai") => 0; + + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "coffee/drip/.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "coffee/coldbrew/./.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "coffee/turkish/././.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "coffee/tubruk/./././.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "coffee/vietnamese/././././.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "coffee/thai/./././././.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + + // still create so we have something to test + lfsr_file_open(&lfs, &file, "coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + } + + // stat paths + struct lfs_info info; + if (DIR) { + lfsr_stat(&lfs, "coffee/drip/./././././.", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == LFS_TYPE_DIR); + lfsr_stat(&lfs, "coffee/coldbrew/././././.", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); + assert(info.type == LFS_TYPE_DIR); + lfsr_stat(&lfs, "coffee/turkish/./././.", &info) => 0; + assert(strcmp(info.name, "turkish") == 0); + assert(info.type == LFS_TYPE_DIR); + lfsr_stat(&lfs, "coffee/tubruk/././.", &info) => 0; + assert(strcmp(info.name, "tubruk") == 0); + assert(info.type == LFS_TYPE_DIR); + lfsr_stat(&lfs, "coffee/vietnamese/./.", &info) => 0; + assert(strcmp(info.name, "vietnamese") == 0); + assert(info.type == LFS_TYPE_DIR); + lfsr_stat(&lfs, "coffee/thai/.", &info) => 0; + assert(strcmp(info.name, "thai") == 0); + assert(info.type == LFS_TYPE_DIR); + } else { + lfsr_stat(&lfs, "coffee/drip/./././././.", &info) => LFS_ERR_NOTDIR; + lfsr_stat(&lfs, "coffee/coldbrew/././././.", &info) => LFS_ERR_NOTDIR; + lfsr_stat(&lfs, "coffee/turkish/./././.", &info) => LFS_ERR_NOTDIR; + lfsr_stat(&lfs, "coffee/tubruk/././.", &info) => LFS_ERR_NOTDIR; + lfsr_stat(&lfs, "coffee/vietnamese/./.", &info) => LFS_ERR_NOTDIR; + lfsr_stat(&lfs, "coffee/thai/.", &info) => LFS_ERR_NOTDIR; + } + + // file open paths, only works on files! + if (DIR) { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "coffee/drip/.", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/coldbrew/./.", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/turkish/././.", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/tubruk/./././.", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/vietnamese/././././.", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/thai/./././././.", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + + lfsr_file_open(&lfs, &file, "coffee/drip/.", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/coldbrew/./.", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/turkish/././.", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/tubruk/./././.", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/vietnamese/././././.", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/thai/./././././.", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfsr_file_open(&lfs, &file, "coffee/drip/.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "coffee/coldbrew/./.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "coffee/turkish/././.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "coffee/tubruk/./././.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "coffee/vietnamese/././././.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "coffee/thai/./././././.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "coffee/drip/.", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/coldbrew/./.", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/turkish/././.", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/tubruk/./././.", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/vietnamese/././././.", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/thai/./././././.", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + + lfsr_file_open(&lfs, &file, "coffee/drip/.", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/coldbrew/./.", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/turkish/././.", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/tubruk/./././.", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/vietnamese/././././.", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/thai/./././././.", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + + lfsr_file_open(&lfs, &file, "coffee/drip/.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/coldbrew/./.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/turkish/././.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/tubruk/./././.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/vietnamese/././././.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/thai/./././././.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + } + + // dir open paths, only works on dirs! + if (DIR) { + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "coffee/drip/.") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "coffee/coldbrew/./.") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "coffee/turkish/././.") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "coffee/tubruk/./././.") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "coffee/vietnamese/././././.") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "coffee/thai/./././././.") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + } else { + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "coffee/drip/.") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "coffee/coldbrew/./.") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "coffee/turkish/././.") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "coffee/tubruk/./././.") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "coffee/vietnamese/././././.") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "coffee/thai/./././././.") => LFS_ERR_NOTDIR; + } + + // rename paths + lfsr_mkdir(&lfs, "espresso") => 0; + if (DIR) { + // bad destination + lfsr_rename(&lfs, + "coffee/drip", + "espresso/espresso/.") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/coldbrew", + "espresso/americano/./.") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/turkish", + "espresso/macchiato/././.") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/tubruk", + "espresso/latte/./././.") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/vietnamese", + "espresso/cappuccino/././././.") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/thai", + "espresso/mocha/./././././.") => LFS_ERR_NOENT; + + // bad source and bad destination + lfsr_rename(&lfs, + "coffee/drip/./././././.", + "espresso/espresso/.") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/coldbrew/././././.", + "espresso/americano/./.") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/turkish/./././.", + "espresso/macchiato/././.") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/tubruk/././.", + "espresso/latte/./././.") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/vietnamese/./.", + "espresso/cappuccino/././././.") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/thai/.", + "espresso/mocha/./././././.") => LFS_ERR_NOENT; + + // this one works + lfsr_rename(&lfs, + "coffee/drip/./././././.", + "espresso/espresso") => 0; + lfsr_rename(&lfs, + "coffee/coldbrew/././././.", + "espresso/americano") => 0; + lfsr_rename(&lfs, + "coffee/turkish/./././.", + "espresso/macchiato") => 0; + lfsr_rename(&lfs, + "coffee/tubruk/././.", + "espresso/latte") => 0; + lfsr_rename(&lfs, + "coffee/vietnamese/./.", + "espresso/cappuccino") => 0; + lfsr_rename(&lfs, + "coffee/thai/.", + "espresso/mocha") => 0; + + // stat paths + lfsr_stat(&lfs, "espresso/espresso/./././././.", &info) => 0; + assert(strcmp(info.name, "espresso") == 0); + assert(info.type == LFS_TYPE_DIR); + lfsr_stat(&lfs, "espresso/americano/././././.", &info) => 0; + assert(strcmp(info.name, "americano") == 0); + assert(info.type == LFS_TYPE_DIR); + lfsr_stat(&lfs, "espresso/macchiato/./././.", &info) => 0; + assert(strcmp(info.name, "macchiato") == 0); + assert(info.type == LFS_TYPE_DIR); + lfsr_stat(&lfs, "espresso/latte/././.", &info) => 0; + assert(strcmp(info.name, "latte") == 0); + assert(info.type == LFS_TYPE_DIR); + lfsr_stat(&lfs, "espresso/cappuccino/./.", &info) => 0; + assert(strcmp(info.name, "cappuccino") == 0); + assert(info.type == LFS_TYPE_DIR); + lfsr_stat(&lfs, "espresso/mocha/.", &info) => 0; + assert(strcmp(info.name, "mocha") == 0); + assert(info.type == LFS_TYPE_DIR); + + lfsr_stat(&lfs, "coffee/drip/./././././.", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/coldbrew/././././.", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/turkish/./././.", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/tubruk/././.", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/vietnamese/./.", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/thai/.", &info) => LFS_ERR_NOENT; + + // remove paths + lfsr_remove(&lfs, "espresso/espresso/.") => 0; + lfsr_remove(&lfs, "espresso/americano/./.") => 0; + lfsr_remove(&lfs, "espresso/macchiato/././.") => 0; + lfsr_remove(&lfs, "espresso/latte/./././.") => 0; + lfsr_remove(&lfs, "espresso/cappuccino/././././.") => 0; + lfsr_remove(&lfs, "espresso/mocha/./././././.") => 0; + + // stat paths + lfsr_stat(&lfs, "espresso/espresso/./././././.", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/americano/././././.", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/macchiato/./././.", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/latte/././.", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/cappuccino/./.", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/mocha/.", &info) => LFS_ERR_NOENT; + + } else { + // bad source + lfsr_rename(&lfs, + "coffee/drip/./././././.", + "espresso/espresso") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "coffee/coldbrew/././././.", + "espresso/americano") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "coffee/turkish/./././.", + "espresso/macchiato") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "coffee/tubruk/././.", + "espresso/latte") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "coffee/vietnamese/./.", + "espresso/cappuccino") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "coffee/thai/.", + "espresso/mocha") => LFS_ERR_NOTDIR; + + // bad destination + lfsr_rename(&lfs, + "coffee/drip", + "espresso/espresso/.") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/coldbrew", + "espresso/americano/./.") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/turkish", + "espresso/macchiato/././.") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/tubruk", + "espresso/latte/./././.") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/vietnamese", + "espresso/cappuccino/././././.") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/thai", + "espresso/mocha/./././././.") => LFS_ERR_NOENT; + + // bad source and bad destination + lfsr_rename(&lfs, + "coffee/drip/./././././.", + "espresso/espresso/.") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "coffee/coldbrew/././././.", + "espresso/americano/./.") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "coffee/turkish/./././.", + "espresso/macchiato/././.") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "coffee/tubruk/././.", + "espresso/latte/./././.") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "coffee/vietnamese/./.", + "espresso/cappuccino/././././.") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "coffee/thai/.", + "espresso/mocha/./././././.") => LFS_ERR_NOTDIR; + + // remove paths + lfsr_remove(&lfs, "coffee/drip/.") => LFS_ERR_NOTDIR; + lfsr_remove(&lfs, "coffee/coldbrew/./.") => LFS_ERR_NOTDIR; + lfsr_remove(&lfs, "coffee/turkish/././.") => LFS_ERR_NOTDIR; + lfsr_remove(&lfs, "coffee/tubruk/./././.") => LFS_ERR_NOTDIR; + lfsr_remove(&lfs, "coffee/vietnamese/././././.") => LFS_ERR_NOTDIR; + lfsr_remove(&lfs, "coffee/thai/./././././.") => LFS_ERR_NOTDIR; + + // stat paths + lfsr_stat(&lfs, "espresso/espresso", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/americano", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/macchiato", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/latte", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/cappuccino", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/mocha", &info) => LFS_ERR_NOENT; + + lfsr_stat(&lfs, "coffee/drip", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == LFS_TYPE_REG); + lfsr_stat(&lfs, "coffee/coldbrew", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); + assert(info.type == LFS_TYPE_REG); + lfsr_stat(&lfs, "coffee/turkish", &info) => 0; + assert(strcmp(info.name, "turkish") == 0); + assert(info.type == LFS_TYPE_REG); + lfsr_stat(&lfs, "coffee/tubruk", &info) => 0; + assert(strcmp(info.name, "tubruk") == 0); + assert(info.type == LFS_TYPE_REG); + lfsr_stat(&lfs, "coffee/vietnamese", &info) => 0; + assert(strcmp(info.name, "vietnamese") == 0); + assert(info.type == LFS_TYPE_REG); + lfsr_stat(&lfs, "coffee/thai", &info) => 0; + assert(strcmp(info.name, "thai") == 0); + assert(info.type == LFS_TYPE_REG); + } + + lfsr_unmount(&lfs) => 0; +''' + +# dot dot path tests +[cases.test_paths_dotdots] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; + lfsr_mount(&lfs, LFS_F_RDWR, CFG) => 0; + + // create paths + lfsr_mkdir(&lfs, "no") => 0; + lfsr_mkdir(&lfs, "no/no") => 0; + lfsr_mkdir(&lfs, "coffee") => 0; + lfsr_mkdir(&lfs, "coffee/no") => 0; + if (DIR) { + lfsr_mkdir(&lfs, "/coffee/drip") => 0; + lfsr_mkdir(&lfs, "/no/../coffee/coldbrew") => 0; + lfsr_mkdir(&lfs, "/coffee/no/../turkish") => 0; + lfsr_mkdir(&lfs, "/no/no/../../coffee/tubruk") => 0; + lfsr_mkdir(&lfs, "/no/no/../../coffee/no/../vietnamese") => 0; + lfsr_mkdir(&lfs, "/no/no/../../no/no/../../coffee/thai") => 0; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/no/../coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/no/../turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/no/no/../../coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/no/no/../../coffee/no/../vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/no/no/../../no/no/../../coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + } + + // stat paths + struct lfs_info info; + lfsr_stat(&lfs, "/no/no/../../no/no/../../coffee/drip", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/no/no/../../coffee/no/../coldbrew", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/no/no/../../coffee/turkish", &info) => 0; + assert(strcmp(info.name, "turkish") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/coffee/no/../tubruk", &info) => 0; + assert(strcmp(info.name, "tubruk") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/no/../coffee/vietnamese", &info) => 0; + assert(strcmp(info.name, "vietnamese") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/coffee/thai", &info) => 0; + assert(strcmp(info.name, "thai") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + // file open paths, only works on files! + if (DIR) { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "/coffee/drip", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/no/../coffee/coldbrew", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/coffee/no/../turkish", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/no/no/../../coffee/tubruk", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/no/no/../../coffee/no/../vietnamese", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/no/no/../../no/no/../../coffee/thai", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + + lfsr_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/no/../coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/coffee/no/../turkish", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/no/no/../../coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/no/no/../../coffee/no/../vietnamese", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/no/no/../../no/no/../../coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfsr_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/no/../coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/coffee/no/../turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/no/no/../../coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/no/no/../../coffee/no/../vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/no/no/../../no/no/../../coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "/coffee/drip", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/no/../coffee/coldbrew", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/no/../turkish", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/no/no/../../coffee/tubruk", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/no/no/../../coffee/no/../vietnamese", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/no/no/../../no/no/../../coffee/thai", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + + lfsr_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/no/../coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/no/../turkish", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/no/no/../../coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/no/no/../../coffee/no/../vietnamese", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/no/no/../../no/no/../../coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + + lfsr_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/no/../coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/coffee/no/../turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/no/no/../../coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/no/no/../../coffee/no/../vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/no/no/../../no/no/../../coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + } + + // dir open paths, only works on dirs! + if (DIR) { + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "/coffee/drip") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "/no/../coffee/coldbrew") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "/coffee/no/../turkish") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "/no/no/../../coffee/tubruk") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "/no/no/../../coffee/no/../vietnamese") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "/no/no/../../no/no/../../coffee/thai") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + } else { + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "/coffee/drip") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "/no/../coffee/coldbrew") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "/coffee/no/../turkish") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "/no/no/../../coffee/tubruk") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "/no/no/../../coffee/no/../vietnamese") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "/no/no/../../no/no/../../coffee/thai") => LFS_ERR_NOTDIR; + } + + // rename paths + lfsr_mkdir(&lfs, "espresso") => 0; + lfsr_rename(&lfs, + "/no/no/../../no/no/../../coffee/drip", + "/espresso/espresso") => 0; + lfsr_rename(&lfs, + "/no/no/../../coffee/no/../coldbrew", + "/no/../espresso/americano") => 0; + lfsr_rename(&lfs, + "/no/no/../../coffee/turkish", + "/espresso/no/../macchiato") => 0; + lfsr_rename(&lfs, + "/coffee/no/../tubruk", + "/no/no/../../espresso/latte") => 0; + lfsr_rename(&lfs, + "/no/../coffee/vietnamese", + "/no/no/../../espresso/no/../cappuccino") => 0; + lfsr_rename(&lfs, + "/coffee/thai", + "/no/no/../../no/no/../../espresso/mocha") => 0; + + // stat paths + lfsr_stat(&lfs, "/no/no/../../no/no/../../espresso/espresso", &info) => 0; + assert(strcmp(info.name, "espresso") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/no/no/../../espresso/no/../americano", &info) => 0; + assert(strcmp(info.name, "americano") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/no/no/../../espresso/macchiato", &info) => 0; + assert(strcmp(info.name, "macchiato") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/espresso/no/../latte", &info) => 0; + assert(strcmp(info.name, "latte") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/no/../espresso/cappuccino", &info) => 0; + assert(strcmp(info.name, "cappuccino") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/espresso/mocha", &info) => 0; + assert(strcmp(info.name, "mocha") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfsr_stat(&lfs, "/no/no/../../no/no/../../coffee/drip", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/no/no/../../coffee/no/../coldbrew", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/no/no/../../coffee/turkish", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/coffee/no/../tubruk", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/no/../coffee/vietnamese", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/coffee/thai", &info) => LFS_ERR_NOENT; + + // remove paths + lfsr_remove(&lfs, "/espresso/espresso") => 0; + lfsr_remove(&lfs, "/no/../espresso/americano") => 0; + lfsr_remove(&lfs, "/espresso/no/../macchiato") => 0; + lfsr_remove(&lfs, "/no/no/../../espresso/latte") => 0; + lfsr_remove(&lfs, "/no/no/../../espresso/no/../cappuccino") => 0; + lfsr_remove(&lfs, "/no/no/../../no/no/../../espresso/mocha") => 0; + + // stat paths + lfsr_stat(&lfs, "/no/no/../../no/no/../../espresso/espresso", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/no/no/../../espresso/no/../americano", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/no/no/../../espresso/macchiato", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/espresso/no/../latte", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/no/../espresso/cappuccino", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/espresso/mocha", &info) => LFS_ERR_NOENT; + + lfsr_unmount(&lfs) => 0; +''' + +# test trailing dot dots, these get really weird +# +# POSIX deviations: +# +# - We do not check for existance of directories followed by dotdots: +# - littlefs: stat("a/missing/..") => 0 +# - POSIX: stat("a/missing/..") => ENOENT +# Reason: Difficult to implement non-recursively. +# +# - We accept modifications of directories with trailing dotdots: +# - littlefs: rename("a/b/..", "c") => 0 +# - POSIX: rename("a/b/..", "c") => EBUSY +# Reason: Not worth implementing. +# +[cases.test_paths_trailing_dotdots] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; + lfsr_mount(&lfs, LFS_F_RDWR, CFG) => 0; + + // create paths + lfsr_mkdir(&lfs, "coffee") => 0; + if (DIR) { + lfsr_mkdir(&lfs, "coffee/drip/..") => LFS_ERR_EXIST; + lfsr_mkdir(&lfs, "coffee/coldbrew/../..") => LFS_ERR_EXIST; + lfsr_mkdir(&lfs, "coffee/turkish/../../..") => LFS_ERR_INVAL; + lfsr_mkdir(&lfs, "coffee/tubruk/../../../..") => LFS_ERR_INVAL; + lfsr_mkdir(&lfs, "coffee/vietnamese/../../../../..") => LFS_ERR_INVAL; + lfsr_mkdir(&lfs, "coffee/thai/../../../../../..") => LFS_ERR_INVAL; + + // still create so we have something to test + lfsr_mkdir(&lfs, "coffee/drip") => 0; + lfsr_mkdir(&lfs, "coffee/coldbrew") => 0; + lfsr_mkdir(&lfs, "coffee/turkish") => 0; + lfsr_mkdir(&lfs, "coffee/tubruk") => 0; + lfsr_mkdir(&lfs, "coffee/vietnamese") => 0; + lfsr_mkdir(&lfs, "coffee/thai") => 0; + + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "coffee/drip/..", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "coffee/coldbrew/../..", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "coffee/turkish/../../..", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; + lfsr_file_open(&lfs, &file, "coffee/tubruk/../../../..", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; + lfsr_file_open(&lfs, &file, "coffee/vietnamese/../../../../..", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; + lfsr_file_open(&lfs, &file, "coffee/thai/../../../../../..", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; + + // still create so we have something to test + lfsr_file_open(&lfs, &file, "coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + } + + // stat paths + struct lfs_info info; + lfsr_stat(&lfs, "coffee/drip/../../../../../..", &info) => LFS_ERR_INVAL; + lfsr_stat(&lfs, "coffee/coldbrew/../../../../..", &info) => LFS_ERR_INVAL; + lfsr_stat(&lfs, "coffee/turkish/../../../..", &info) => LFS_ERR_INVAL; + lfsr_stat(&lfs, "coffee/tubruk/../../..", &info) => LFS_ERR_INVAL; + lfsr_stat(&lfs, "coffee/vietnamese/../..", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); + lfsr_stat(&lfs, "coffee/thai/..", &info) => 0; + assert(strcmp(info.name, "coffee") == 0); + assert(info.type == LFS_TYPE_DIR); + + // file open paths, only works on files! + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "coffee/drip/..", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/coldbrew/../..", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/turkish/../../..", + LFS_O_RDONLY) => LFS_ERR_INVAL; + lfsr_file_open(&lfs, &file, "coffee/tubruk/../../../..", + LFS_O_RDONLY) => LFS_ERR_INVAL; + lfsr_file_open(&lfs, &file, "coffee/vietnamese/../../../../..", + LFS_O_RDONLY) => LFS_ERR_INVAL; + lfsr_file_open(&lfs, &file, "coffee/thai/../../../../../..", + LFS_O_RDONLY) => LFS_ERR_INVAL; + + lfsr_file_open(&lfs, &file, "coffee/drip/..", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/coldbrew/../..", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/turkish/../../..", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_INVAL; + lfsr_file_open(&lfs, &file, "coffee/tubruk/../../../..", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_INVAL; + lfsr_file_open(&lfs, &file, "coffee/vietnamese/../../../../..", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_INVAL; + lfsr_file_open(&lfs, &file, "coffee/thai/../../../../../..", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_INVAL; + + lfsr_file_open(&lfs, &file, "coffee/drip/..", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "coffee/coldbrew/../..", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "coffee/turkish/../../..", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; + lfsr_file_open(&lfs, &file, "coffee/tubruk/../../../..", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; + lfsr_file_open(&lfs, &file, "coffee/vietnamese/../../../../..", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; + lfsr_file_open(&lfs, &file, "coffee/thai/../../../../../..", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; + + // dir open paths, only works on dirs! + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "coffee/drip/..") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "coffee/coldbrew/../..") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "coffee/turkish/../../..") => LFS_ERR_INVAL; + lfsr_dir_open(&lfs, &dir, "coffee/tubruk/../../../..") => LFS_ERR_INVAL; + lfsr_dir_open(&lfs, &dir, "coffee/vietnamese/../../../../..") => LFS_ERR_INVAL; + lfsr_dir_open(&lfs, &dir, "coffee/thai/../../../../../..") => LFS_ERR_INVAL; + + // rename paths + lfsr_mkdir(&lfs, "espresso") => 0; + // bad source + lfsr_rename(&lfs, + "coffee/drip/../../../../../..", + "espresso/espresso") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "coffee/coldbrew/../../../../..", + "espresso/americano") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "coffee/turkish/../../../..", + "espresso/macchiato") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "coffee/tubruk/../../..", + "espresso/latte") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "coffee/vietnamese/../..", + "espresso/cappuccino") => LFS_ERR_INVAL; + // this one works + lfsr_rename(&lfs, + "coffee/thai/..", + "espresso/mocha") => 0; + lfsr_rename(&lfs, + "espresso/mocha", + "coffee") => 0; + + // bad destination + if (DIR) { + // this one works + lfsr_rename(&lfs, + "coffee/drip", + "espresso/espresso/..") => 0; + lfsr_rename(&lfs, + "espresso", + "coffee/drip") => 0; + } else { + lfsr_rename(&lfs, + "coffee/drip", + "espresso/espresso/..") => LFS_ERR_ISDIR; + } + lfsr_rename(&lfs, + "coffee/coldbrew", + "espresso/americano/../..") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "coffee/turkish", + "espresso/macchiato/../../..") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "coffee/tubruk", + "espresso/latte/../../../..") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "coffee/vietnamese", + "espresso/cappuccino/../../../../..") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "coffee/thai", + "espresso/mocha/../../../../../..") => LFS_ERR_INVAL; + + // bad source and bad destination + lfsr_rename(&lfs, + "coffee/drip/../../../../../..", + "espresso/espresso/..") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "coffee/coldbrew/../../../../..", + "espresso/americano/../..") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "coffee/turkish/../../../..", + "espresso/macchiato/../../..") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "coffee/tubruk/../../..", + "espresso/latte/../../../..") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "coffee/vietnamese/../..", + "espresso/cappuccino/../../../../..") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "coffee/thai/..", + "espresso/mocha/../../../../../..") => LFS_ERR_INVAL; + + // remove paths + lfsr_remove(&lfs, "coffee/drip/..") => LFS_ERR_NOTEMPTY; + lfsr_remove(&lfs, "coffee/coldbrew/../..") => LFS_ERR_INVAL; + lfsr_remove(&lfs, "coffee/turkish/../../..") => LFS_ERR_INVAL; + lfsr_remove(&lfs, "coffee/tubruk/../../../..") => LFS_ERR_INVAL; + lfsr_remove(&lfs, "coffee/vietnamese/../../../../..") => LFS_ERR_INVAL; + lfsr_remove(&lfs, "coffee/thai/../../../../../..") => LFS_ERR_INVAL; + + // stat paths + lfsr_stat(&lfs, "espresso/espresso", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/americano", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/macchiato", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/latte", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/cappuccino", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/mocha", &info) => LFS_ERR_NOENT; + + lfsr_stat(&lfs, "coffee/drip", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/coldbrew", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/turkish", &info) => 0; + assert(strcmp(info.name, "turkish") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/tubruk", &info) => 0; + assert(strcmp(info.name, "tubruk") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/vietnamese", &info) => 0; + assert(strcmp(info.name, "vietnamese") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/thai", &info) => 0; + assert(strcmp(info.name, "thai") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfsr_unmount(&lfs) => 0; +''' + +# dot dot dot path tests +[cases.test_paths_dot_dotdots] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; + lfsr_mount(&lfs, LFS_F_RDWR, CFG) => 0; + + // create paths + lfsr_mkdir(&lfs, "no") => 0; + lfsr_mkdir(&lfs, "no/no") => 0; + lfsr_mkdir(&lfs, "coffee") => 0; + lfsr_mkdir(&lfs, "coffee/no") => 0; + if (DIR) { + lfsr_mkdir(&lfs, "/coffee/drip") => 0; + lfsr_mkdir(&lfs, "/no/./../coffee/coldbrew") => 0; + lfsr_mkdir(&lfs, "/coffee/no/./../turkish") => 0; + lfsr_mkdir(&lfs, "/no/no/./.././../coffee/tubruk") => 0; + lfsr_mkdir(&lfs, "/no/no/./.././../coffee/no/./../vietnamese") => 0; + lfsr_mkdir(&lfs, "/no/no/./.././../no/no/./.././../coffee/thai") => 0; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/no/./../coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/no/./../turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/no/no/./.././../coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/no/no/./.././../coffee/no/./../vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/no/no/./.././../no/no/./.././../coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + } + + // stat paths + struct lfs_info info; + lfsr_stat(&lfs, "/no/no/./.././../no/no/./.././../coffee/drip", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/no/no/./.././../coffee/no/./../coldbrew", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/no/no/./.././../coffee/turkish", &info) => 0; + assert(strcmp(info.name, "turkish") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/coffee/no/./../tubruk", &info) => 0; + assert(strcmp(info.name, "tubruk") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/no/./../coffee/vietnamese", &info) => 0; + assert(strcmp(info.name, "vietnamese") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/coffee/thai", &info) => 0; + assert(strcmp(info.name, "thai") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + // file open paths, only works on files! + if (DIR) { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "/coffee/drip", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/no/./../coffee/coldbrew", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/coffee/no/./../turkish", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/no/no/./.././../coffee/tubruk", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/no/no/./.././../coffee/no/./../vietnamese", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/no/no/./.././../no/no/./.././../coffee/thai", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + + lfsr_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/no/./../coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/coffee/no/./../turkish", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/no/no/./.././../coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/no/no/./.././../coffee/no/./../vietnamese", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/no/no/./.././../no/no/./.././../coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfsr_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/no/./../coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/coffee/no/./../turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/no/no/./.././../coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/no/no/./.././../coffee/no/./../vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/no/no/./.././../no/no/./.././../coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "/coffee/drip", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/no/./../coffee/coldbrew", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/no/./../turkish", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/no/no/./.././../coffee/tubruk", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/no/no/./.././../coffee/no/./../vietnamese", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/no/no/./.././../no/no/./.././../coffee/thai", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + + lfsr_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/no/./../coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/no/./../turkish", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/no/no/./.././../coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/no/no/./.././../coffee/no/./../vietnamese", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/no/no/./.././../no/no/./.././../coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + + lfsr_file_open(&lfs, &file, "/coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/no/./../coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/coffee/no/./../turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/no/no/./.././../coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/no/no/./.././../coffee/no/./../vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/no/no/./.././../no/no/./.././../coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + } + + // dir open paths, only works on dirs! + if (DIR) { + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "/coffee/drip") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "/no/./../coffee/coldbrew") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "/coffee/no/./../turkish") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "/no/no/./.././../coffee/tubruk") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "/no/no/./.././../coffee/no/./../vietnamese") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "/no/no/./.././../no/no/./.././../coffee/thai") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + } else { + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "/coffee/drip") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "/no/./../coffee/coldbrew") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "/coffee/no/./../turkish") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "/no/no/./.././../coffee/tubruk") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "/no/no/./.././../coffee/no/./../vietnamese") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "/no/no/./.././../no/no/./.././../coffee/thai") => LFS_ERR_NOTDIR; + } + + // rename paths + lfsr_mkdir(&lfs, "espresso") => 0; + lfsr_rename(&lfs, + "/no/no/./.././../no/no/./.././../coffee/drip", + "/espresso/espresso") => 0; + lfsr_rename(&lfs, + "/no/no/./.././../coffee/no/./../coldbrew", + "/no/./../espresso/americano") => 0; + lfsr_rename(&lfs, + "/no/no/./.././../coffee/turkish", + "/espresso/no/./../macchiato") => 0; + lfsr_rename(&lfs, + "/coffee/no/./../tubruk", + "/no/no/./.././../espresso/latte") => 0; + lfsr_rename(&lfs, + "/no/./../coffee/vietnamese", + "/no/no/./.././../espresso/no/./../cappuccino") => 0; + lfsr_rename(&lfs, + "/coffee/thai", + "/no/no/./.././../no/no/./.././../espresso/mocha") => 0; + + // stat paths + lfsr_stat(&lfs, "/no/no/./.././../no/no/./.././../espresso/espresso", &info) => 0; + assert(strcmp(info.name, "espresso") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/no/no/./.././../espresso/no/./../americano", &info) => 0; + assert(strcmp(info.name, "americano") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/no/no/./.././../espresso/macchiato", &info) => 0; + assert(strcmp(info.name, "macchiato") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/espresso/no/./../latte", &info) => 0; + assert(strcmp(info.name, "latte") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/no/./../espresso/cappuccino", &info) => 0; + assert(strcmp(info.name, "cappuccino") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/espresso/mocha", &info) => 0; + assert(strcmp(info.name, "mocha") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfsr_stat(&lfs, "/no/no/./.././../no/no/./.././../coffee/drip", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/no/no/./.././../coffee/no/./../coldbrew", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/no/no/./.././../coffee/turkish", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/coffee/no/./../tubruk", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/no/./../coffee/vietnamese", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/coffee/thai", &info) => LFS_ERR_NOENT; + + // remove paths + lfsr_remove(&lfs, "/espresso/espresso") => 0; + lfsr_remove(&lfs, "/no/./../espresso/americano") => 0; + lfsr_remove(&lfs, "/espresso/no/./../macchiato") => 0; + lfsr_remove(&lfs, "/no/no/./.././../espresso/latte") => 0; + lfsr_remove(&lfs, "/no/no/./.././../espresso/no/./../cappuccino") => 0; + lfsr_remove(&lfs, "/no/no/./.././../no/no/./.././../espresso/mocha") => 0; + + // stat paths + lfsr_stat(&lfs, "/no/no/./.././../no/no/./.././../espresso/espresso", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/no/no/./.././../espresso/no/./../americano", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/no/no/./.././../espresso/macchiato", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/espresso/no/./../latte", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/no/./../espresso/cappuccino", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/espresso/mocha", &info) => LFS_ERR_NOENT; + + lfsr_unmount(&lfs) => 0; +''' + +# dot dot dot path tests +[cases.test_paths_dotdotdots] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; + lfsr_mount(&lfs, LFS_F_RDWR, CFG) => 0; + + // create paths + lfsr_mkdir(&lfs, "coffee") => 0; + lfsr_mkdir(&lfs, "coffee/...") => 0; + if (DIR) { + lfsr_mkdir(&lfs, "/coffee/.../drip") => 0; + lfsr_mkdir(&lfs, "/coffee/.../coldbrew") => 0; + lfsr_mkdir(&lfs, "/coffee/.../turkish") => 0; + lfsr_mkdir(&lfs, "/coffee/.../tubruk") => 0; + lfsr_mkdir(&lfs, "/coffee/.../vietnamese") => 0; + lfsr_mkdir(&lfs, "/coffee/.../thai") => 0; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "/coffee/.../drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/.../coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/.../turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/.../tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/.../vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/.../thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + } + + // stat paths + struct lfs_info info; + lfsr_stat(&lfs, "/coffee/.../drip", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/coffee/.../coldbrew", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/coffee/.../turkish", &info) => 0; + assert(strcmp(info.name, "turkish") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/coffee/.../tubruk", &info) => 0; + assert(strcmp(info.name, "tubruk") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/coffee/.../vietnamese", &info) => 0; + assert(strcmp(info.name, "vietnamese") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/coffee/.../thai", &info) => 0; + assert(strcmp(info.name, "thai") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + // file open paths, only works on files! + if (DIR) { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "/coffee/.../drip", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/coffee/.../coldbrew", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/coffee/.../turkish", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/coffee/.../tubruk", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/coffee/.../vietnamese", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/coffee/.../thai", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + + lfsr_file_open(&lfs, &file, "/coffee/.../drip", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/coffee/.../coldbrew", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/coffee/.../turkish", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/coffee/.../tubruk", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/coffee/.../vietnamese", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/coffee/.../thai", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfsr_file_open(&lfs, &file, "/coffee/.../drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/coffee/.../coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/coffee/.../turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/coffee/.../tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/coffee/.../vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/coffee/.../thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "/coffee/.../drip", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/.../coldbrew", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/.../turkish", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/.../tubruk", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/.../vietnamese", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/.../thai", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + + lfsr_file_open(&lfs, &file, "/coffee/.../drip", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/.../coldbrew", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/.../turkish", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/.../tubruk", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/.../vietnamese", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/.../thai", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + + lfsr_file_open(&lfs, &file, "/coffee/.../drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/coffee/.../coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/coffee/.../turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/coffee/.../tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/coffee/.../vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/coffee/.../thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + } + + // dir open paths, only works on dirs! + if (DIR) { + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "/coffee/.../drip") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "/coffee/.../coldbrew") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "/coffee/.../turkish") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "/coffee/.../tubruk") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "/coffee/.../vietnamese") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "/coffee/.../thai") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + } else { + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "/coffee/.../drip") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "/coffee/.../coldbrew") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "/coffee/.../turkish") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "/coffee/.../tubruk") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "/coffee/.../vietnamese") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "/coffee/.../thai") => LFS_ERR_NOTDIR; + } + + // rename paths + lfsr_mkdir(&lfs, "espresso") => 0; + lfsr_mkdir(&lfs, "espresso/...") => 0; + lfsr_rename(&lfs, + "/coffee/.../drip", + "/espresso/.../espresso") => 0; + lfsr_rename(&lfs, + "/coffee/.../coldbrew", + "/espresso/.../americano") => 0; + lfsr_rename(&lfs, + "/coffee/.../turkish", + "/espresso/.../macchiato") => 0; + lfsr_rename(&lfs, + "/coffee/.../tubruk", + "/espresso/.../latte") => 0; + lfsr_rename(&lfs, + "/coffee/.../vietnamese", + "/espresso/.../cappuccino") => 0; + lfsr_rename(&lfs, + "/coffee/.../thai", + "/espresso/.../mocha") => 0; + + // stat paths + lfsr_stat(&lfs, "/espresso/.../espresso", &info) => 0; + assert(strcmp(info.name, "espresso") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/espresso/.../americano", &info) => 0; + assert(strcmp(info.name, "americano") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/espresso/.../macchiato", &info) => 0; + assert(strcmp(info.name, "macchiato") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/espresso/.../latte", &info) => 0; + assert(strcmp(info.name, "latte") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/espresso/.../cappuccino", &info) => 0; + assert(strcmp(info.name, "cappuccino") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/espresso/.../mocha", &info) => 0; + assert(strcmp(info.name, "mocha") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfsr_stat(&lfs, "coffee/.../drip", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/.../coldbrew", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/.../turkish", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/.../tubruk", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/.../vietnamese", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/.../thai", &info) => LFS_ERR_NOENT; + + // remove paths + lfsr_remove(&lfs, "/espresso/.../espresso") => 0; + lfsr_remove(&lfs, "/espresso/.../americano") => 0; + lfsr_remove(&lfs, "/espresso/.../macchiato") => 0; + lfsr_remove(&lfs, "/espresso/.../latte") => 0; + lfsr_remove(&lfs, "/espresso/.../cappuccino") => 0; + lfsr_remove(&lfs, "/espresso/.../mocha") => 0; + + // stat paths + lfsr_stat(&lfs, "/espresso/.../espresso", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/espresso/.../americano", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/espresso/.../macchiato", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/espresso/.../latte", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/espresso/.../cappuccino", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/espresso/.../mocha", &info) => LFS_ERR_NOENT; + lfsr_unmount(&lfs) => 0; ''' # leading dot path test -[cases.test_paths_leading_dot] +[cases.test_paths_leading_dots] +defines.DIR = [false, true] code = ''' lfs_t lfs; lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; - lfsr_mkdir(&lfs, ".milk") => 0; + lfsr_mount(&lfs, LFS_F_RDWR, CFG) => 0; + + // create paths + lfsr_mkdir(&lfs, "coffee") => 0; + if (DIR) { + lfsr_mkdir(&lfs, "/coffee/.drip") => 0; + lfsr_mkdir(&lfs, "/coffee/..coldbrew") => 0; + lfsr_mkdir(&lfs, "/coffee/...turkish") => 0; + lfsr_mkdir(&lfs, "/coffee/....tubruk") => 0; + lfsr_mkdir(&lfs, "/coffee/.....vietnamese") => 0; + lfsr_mkdir(&lfs, "/coffee/......thai") => 0; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "/coffee/.drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/..coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/...turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/....tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/.....vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/......thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + } + + // stat paths struct lfs_info info; - lfsr_stat(&lfs, ".milk", &info) => 0; - strcmp(info.name, ".milk") => 0; - lfsr_stat(&lfs, "tea/.././.milk", &info) => 0; - strcmp(info.name, ".milk") => 0; + lfsr_stat(&lfs, "/coffee/.drip", &info) => 0; + assert(strcmp(info.name, ".drip") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/coffee/..coldbrew", &info) => 0; + assert(strcmp(info.name, "..coldbrew") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/coffee/...turkish", &info) => 0; + assert(strcmp(info.name, "...turkish") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/coffee/....tubruk", &info) => 0; + assert(strcmp(info.name, "....tubruk") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/coffee/.....vietnamese", &info) => 0; + assert(strcmp(info.name, ".....vietnamese") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/coffee/......thai", &info) => 0; + assert(strcmp(info.name, "......thai") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + // file open paths, only works on files! + if (DIR) { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "/coffee/.drip", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/coffee/..coldbrew", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/coffee/...turkish", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/coffee/....tubruk", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/coffee/.....vietnamese", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/coffee/......thai", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + + lfsr_file_open(&lfs, &file, "/coffee/.drip", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/coffee/..coldbrew", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/coffee/...turkish", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/coffee/....tubruk", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/coffee/.....vietnamese", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/coffee/......thai", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfsr_file_open(&lfs, &file, "/coffee/.drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/coffee/..coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/coffee/...turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/coffee/....tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/coffee/.....vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/coffee/......thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "/coffee/.drip", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/..coldbrew", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/...turkish", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/....tubruk", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/.....vietnamese", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/......thai", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + + lfsr_file_open(&lfs, &file, "/coffee/.drip", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/..coldbrew", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/...turkish", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/....tubruk", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/.....vietnamese", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "/coffee/......thai", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + + lfsr_file_open(&lfs, &file, "/coffee/.drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/coffee/..coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/coffee/...turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/coffee/....tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/coffee/.....vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/coffee/......thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + } + + // dir open paths, only works on dirs! + if (DIR) { + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "/coffee/.drip") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "/coffee/..coldbrew") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "/coffee/...turkish") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "/coffee/....tubruk") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "/coffee/.....vietnamese") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "/coffee/......thai") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + } else { + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "/coffee/.drip") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "/coffee/..coldbrew") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "/coffee/...turkish") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "/coffee/....tubruk") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "/coffee/.....vietnamese") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "/coffee/......thai") => LFS_ERR_NOTDIR; + } + + // rename paths + lfsr_mkdir(&lfs, "espresso") => 0; + lfsr_rename(&lfs, + "/coffee/.drip", + "/espresso/.espresso") => 0; + lfsr_rename(&lfs, + "/coffee/..coldbrew", + "/espresso/..americano") => 0; + lfsr_rename(&lfs, + "/coffee/...turkish", + "/espresso/...macchiato") => 0; + lfsr_rename(&lfs, + "/coffee/....tubruk", + "/espresso/....latte") => 0; + lfsr_rename(&lfs, + "/coffee/.....vietnamese", + "/espresso/.....cappuccino") => 0; + lfsr_rename(&lfs, + "/coffee/......thai", + "/espresso/......mocha") => 0; + + // stat paths + lfsr_stat(&lfs, "/espresso/.espresso", &info) => 0; + assert(strcmp(info.name, ".espresso") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/espresso/..americano", &info) => 0; + assert(strcmp(info.name, "..americano") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/espresso/...macchiato", &info) => 0; + assert(strcmp(info.name, "...macchiato") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/espresso/....latte", &info) => 0; + assert(strcmp(info.name, "....latte") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/espresso/.....cappuccino", &info) => 0; + assert(strcmp(info.name, ".....cappuccino") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "/espresso/......mocha", &info) => 0; + assert(strcmp(info.name, "......mocha") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfsr_stat(&lfs, "coffee/.drip", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/..coldbrew", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/...turkish", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/....tubruk", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/.....vietnamese", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/......thai", &info) => LFS_ERR_NOENT; + + // remove paths + lfsr_remove(&lfs, "/espresso/.espresso") => 0; + lfsr_remove(&lfs, "/espresso/..americano") => 0; + lfsr_remove(&lfs, "/espresso/...macchiato") => 0; + lfsr_remove(&lfs, "/espresso/....latte") => 0; + lfsr_remove(&lfs, "/espresso/.....cappuccino") => 0; + lfsr_remove(&lfs, "/espresso/......mocha") => 0; + + // stat paths + lfsr_stat(&lfs, "/espresso/.espresso", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/espresso/..americano", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/espresso/...macchiato", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/espresso/....latte", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/espresso/.....cappuccino", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "/espresso/......mocha", &info) => LFS_ERR_NOENT; + lfsr_unmount(&lfs) => 0; ''' # root dot dot path test -[cases.test_paths_root_dot_dot] +[cases.test_paths_root_dotdots] +defines.DIR = [false, true] code = ''' lfs_t lfs; lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; - lfsr_mkdir(&lfs, "tea") => 0; - lfsr_mkdir(&lfs, "tea/green") => 0; - lfsr_mkdir(&lfs, "tea/oolong") => 0; - lfsr_mkdir(&lfs, "tea/black") => 0; + lfsr_mount(&lfs, LFS_F_RDWR, CFG) => 0; + + // create paths + lfsr_mkdir(&lfs, "no") => 0; lfsr_mkdir(&lfs, "coffee") => 0; - lfsr_mkdir(&lfs, "coffee/drip") => 0; - lfsr_mkdir(&lfs, "coffee/espresso") => 0; - lfsr_mkdir(&lfs, "coffee/coldbrew") => 0; + if (DIR) { + lfsr_mkdir(&lfs, "/../coffee/drip") => LFS_ERR_INVAL; + lfsr_mkdir(&lfs, "/../../coffee/coldbrew") => LFS_ERR_INVAL; + lfsr_mkdir(&lfs, "/../../../coffee/turkish") => LFS_ERR_INVAL; + lfsr_mkdir(&lfs, "/no/../../coffee/tubruk") => LFS_ERR_INVAL; + lfsr_mkdir(&lfs, "/no/../../../coffee/vietnamese") => LFS_ERR_INVAL; + lfsr_mkdir(&lfs, "/no/../../../../coffee/thai") => LFS_ERR_INVAL; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "/../coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; + lfsr_file_open(&lfs, &file, "/../../coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; + lfsr_file_open(&lfs, &file, "/../../../coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; + lfsr_file_open(&lfs, &file, "/no/../../coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; + lfsr_file_open(&lfs, &file, "/no/../../../coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; + lfsr_file_open(&lfs, &file, "/no/../../../../coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; + } + // ok, actually create paths + if (DIR) { + lfsr_mkdir(&lfs, "coffee/drip") => 0; + lfsr_mkdir(&lfs, "coffee/coldbrew") => 0; + lfsr_mkdir(&lfs, "coffee/turkish") => 0; + lfsr_mkdir(&lfs, "coffee/tubruk") => 0; + lfsr_mkdir(&lfs, "coffee/vietnamese") => 0; + lfsr_mkdir(&lfs, "coffee/thai") => 0; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + } + + // stat paths struct lfs_info info; - lfsr_stat(&lfs, "coffee/../../../../../../tea/green", &info) => 0; - strcmp(info.name, "green") => 0; + lfsr_stat(&lfs, "/no/../../../../coffee/drip", &info) => LFS_ERR_INVAL; + lfsr_stat(&lfs, "/no/../../../coffee/coldbrew", &info) => LFS_ERR_INVAL; + lfsr_stat(&lfs, "/no/../../coffee/turkish", &info) => LFS_ERR_INVAL; + lfsr_stat(&lfs, "/../../../coffee/tubruk", &info) => LFS_ERR_INVAL; + lfsr_stat(&lfs, "/../../coffee/vietnamese", &info) => LFS_ERR_INVAL; + lfsr_stat(&lfs, "/../coffee/thai", &info) => LFS_ERR_INVAL; + + // file open paths, only works on files! + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "/../coffee/drip", + LFS_O_RDONLY) => LFS_ERR_INVAL; + lfsr_file_open(&lfs, &file, "/../../coffee/coldbrew", + LFS_O_RDONLY) => LFS_ERR_INVAL; + lfsr_file_open(&lfs, &file, "/../../../coffee/turkish", + LFS_O_RDONLY) => LFS_ERR_INVAL; + lfsr_file_open(&lfs, &file, "/no/../../coffee/tubruk", + LFS_O_RDONLY) => LFS_ERR_INVAL; + lfsr_file_open(&lfs, &file, "/no/../../../coffee/vietnamese", + LFS_O_RDONLY) => LFS_ERR_INVAL; + lfsr_file_open(&lfs, &file, "/no/../../../../coffee/thai", + LFS_O_RDONLY) => LFS_ERR_INVAL; + + lfsr_file_open(&lfs, &file, "/../coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_INVAL; + lfsr_file_open(&lfs, &file, "/../../coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_INVAL; + lfsr_file_open(&lfs, &file, "/../../../coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_INVAL; + lfsr_file_open(&lfs, &file, "/no/../../coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_INVAL; + lfsr_file_open(&lfs, &file, "/no/../../../coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_INVAL; + lfsr_file_open(&lfs, &file, "/no/../../../../coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_INVAL; + + lfsr_file_open(&lfs, &file, "/../coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; + lfsr_file_open(&lfs, &file, "/../../coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; + lfsr_file_open(&lfs, &file, "/../../../coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; + lfsr_file_open(&lfs, &file, "/no/../../coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; + lfsr_file_open(&lfs, &file, "/no/../../../coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; + lfsr_file_open(&lfs, &file, "/no/../../../../coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; + + // dir open paths, only works on dirs! + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "/../coffee/drip") => LFS_ERR_INVAL; + lfsr_dir_open(&lfs, &dir, "/../../coffee/coldbrew") => LFS_ERR_INVAL; + lfsr_dir_open(&lfs, &dir, "/../../../coffee/turkish") => LFS_ERR_INVAL; + lfsr_dir_open(&lfs, &dir, "/no/../../coffee/tubruk") => LFS_ERR_INVAL; + lfsr_dir_open(&lfs, &dir, "/no/../../../coffee/vietnamese") => LFS_ERR_INVAL; + lfsr_dir_open(&lfs, &dir, "/no/../../../../coffee/thai") => LFS_ERR_INVAL; + + // rename paths + lfsr_mkdir(&lfs, "espresso") => 0; + // bad source + lfsr_rename(&lfs, + "/no/../../../../coffee/drip", + "espresso/espresso") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "/no/../../../coffee/coldbrew", + "espresso/americano") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "/no/../../coffee/turkish", + "espresso/macchiato") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "/../../../coffee/tubruk", + "espresso/latte") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "/../../coffee/vietnamese", + "espresso/cappuccino") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "/../coffee/thai", + "espresso/mocha") => LFS_ERR_INVAL; + + // bad destination + lfsr_rename(&lfs, + "coffee/drip", + "/../espresso/espresso") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "coffee/coldbrew", + "/../../espresso/americano") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "coffee/turkish", + "/../../../espresso/macchiato") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "coffee/tubruk", + "/no/../../espresso/latte") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "coffee/vietnamese", + "/no/../../../espresso/cappuccino") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "coffee/thai", + "/no/../../../../espresso/mocha") => LFS_ERR_INVAL; + + // bad source and bad destination + lfsr_rename(&lfs, + "/no/../../../../coffee/drip", + "/../espresso/espresso") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "/no/../../../coffee/coldbrew", + "/../../espresso/americano") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "/no/../../coffee/turkish", + "/../../../espresso/macchiato") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "/../../../coffee/tubruk", + "/no/../../espresso/latte") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "/../../coffee/vietnamese", + "/no/../../../espresso/cappuccino") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "/../coffee/thai", + "/no/../../../../espresso/mocha") => LFS_ERR_INVAL; + + // here's a weird one, what happens if our rename is also a noop? + lfsr_rename(&lfs, + "/no/../../../../coffee/drip", + "/no/../../../../coffee/drip") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "/no/../../../coffee/coldbrew", + "/no/../../../coffee/coldbrew") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "/no/../../coffee/turkish", + "/no/../../coffee/turkish") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "/../../../coffee/tubruk", + "/../../../coffee/tubruk") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "/../../coffee/vietnamese", + "/../../coffee/vietnamese") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "/../coffee/thai", + "/../coffee/thai") => LFS_ERR_INVAL; + + // remove paths + lfsr_remove(&lfs, "/../espresso/espresso") => LFS_ERR_INVAL; + lfsr_remove(&lfs, "/../../espresso/americano") => LFS_ERR_INVAL; + lfsr_remove(&lfs, "/../../../espresso/macchiato") => LFS_ERR_INVAL; + lfsr_remove(&lfs, "/no/../../espresso/latte") => LFS_ERR_INVAL; + lfsr_remove(&lfs, "/no/../../../espresso/cappuccino") => LFS_ERR_INVAL; + lfsr_remove(&lfs, "/no/../../../../espresso/mocha") => LFS_ERR_INVAL; + + // stat paths + lfsr_stat(&lfs, "espresso/espresso", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/americano", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/macchiato", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/latte", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/cappuccino", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/mocha", &info) => LFS_ERR_NOENT; + + lfsr_stat(&lfs, "coffee/drip", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/coldbrew", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/turkish", &info) => 0; + assert(strcmp(info.name, "turkish") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/tubruk", &info) => 0; + assert(strcmp(info.name, "tubruk") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/vietnamese", &info) => 0; + assert(strcmp(info.name, "vietnamese") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/thai", &info) => 0; + assert(strcmp(info.name, "thai") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); - lfsr_mkdir(&lfs, "coffee/../../../../../../milk") => 0; - lfsr_stat(&lfs, "coffee/../../../../../../milk", &info) => 0; - strcmp(info.name, "milk") => 0; - lfsr_stat(&lfs, "milk", &info) => 0; - strcmp(info.name, "milk") => 0; lfsr_unmount(&lfs) => 0; ''' -# invalid path tests -[cases.test_paths_invalid] +# trailing noent tests +[cases.test_paths_noent] +defines.DIR = [false, true] code = ''' lfs_t lfs; lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; + lfsr_mount(&lfs, LFS_F_RDWR, CFG) => 0; + + // create paths + lfsr_mkdir(&lfs, "coffee") => 0; + if (DIR) { + lfsr_mkdir(&lfs, "coffee/drip") => 0; + lfsr_mkdir(&lfs, "coffee/coldbrew") => 0; + lfsr_mkdir(&lfs, "coffee/turkish") => 0; + lfsr_mkdir(&lfs, "coffee/tubruk") => 0; + lfsr_mkdir(&lfs, "coffee/vietnamese") => 0; + lfsr_mkdir(&lfs, "coffee/thai") => 0; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + } + + // stat paths struct lfs_info info; - lfsr_stat(&lfs, "milk", &info) => LFS_ERR_NOENT; - lfsr_stat(&lfs, "milk/cream", &info) => LFS_ERR_NOENT; - lfsr_stat(&lfs, "milk/cream/foam", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/_rip", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/c_ldbrew", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/tu_kish", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/tub_uk", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/_vietnamese", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/thai_", &info) => LFS_ERR_NOENT; - lfsr_remove(&lfs, "milk") => LFS_ERR_NOENT; - lfsr_remove(&lfs, "milk/cream") => LFS_ERR_NOENT; - lfsr_remove(&lfs, "milk/cream/foam") => LFS_ERR_NOENT; - - lfsr_mkdir(&lfs, "milk/cream") => LFS_ERR_NOENT; + // file open paths, only works on files! lfsr_file_t file; - lfsr_file_open(&lfs, &file, "milk/cream", + lfsr_file_open(&lfs, &file, "coffee/_rip", + LFS_O_RDONLY) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "coffee/c_ldbrew", + LFS_O_RDONLY) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "coffee/tu_kish", + LFS_O_RDONLY) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "coffee/tub_uk", + LFS_O_RDONLY) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "coffee/_vietnamese", + LFS_O_RDONLY) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "coffee/thai_", + LFS_O_RDONLY) => LFS_ERR_NOENT; + + // dir open paths, only works on dirs! + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "coffee/_rip") => LFS_ERR_NOENT; + lfsr_dir_open(&lfs, &dir, "coffee/c_ldbrew") => LFS_ERR_NOENT; + lfsr_dir_open(&lfs, &dir, "coffee/tu_kish") => LFS_ERR_NOENT; + lfsr_dir_open(&lfs, &dir, "coffee/tub_uk") => LFS_ERR_NOENT; + lfsr_dir_open(&lfs, &dir, "coffee/_vietnamese") => LFS_ERR_NOENT; + lfsr_dir_open(&lfs, &dir, "coffee/thai_") => LFS_ERR_NOENT; + + // rename paths + lfsr_mkdir(&lfs, "espresso") => 0; + lfsr_rename(&lfs, + "coffee/_rip", + "espresso/espresso") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/c_ldbrew", + "espresso/americano") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/tu_kish", + "espresso/macchiato") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/tub_uk", + "espresso/latte") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/_vietnamese", + "espresso/cappuccino") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/thai_", + "espresso/mocha") => LFS_ERR_NOENT; + + // here's a weird one, what happens if our rename is also a noop? + lfsr_rename(&lfs, + "coffee/_rip", + "coffee/_rip") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/c_ldbrew", + "coffee/c_ldbrew") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/tu_kish", + "coffee/tu_kish") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/tub_uk", + "coffee/tub_uk") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/_vietnamese", + "coffee/_vietnamese") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/thai_", + "coffee/thai_") => LFS_ERR_NOENT; + + // remove paths + lfsr_remove(&lfs, "coffee/_rip") => LFS_ERR_NOENT; + lfsr_remove(&lfs, "coffee/c_ldbrew") => LFS_ERR_NOENT; + lfsr_remove(&lfs, "coffee/tu_kish") => LFS_ERR_NOENT; + lfsr_remove(&lfs, "coffee/tub_uk") => LFS_ERR_NOENT; + lfsr_remove(&lfs, "coffee/_vietnamese") => LFS_ERR_NOENT; + lfsr_remove(&lfs, "coffee/thai_") => LFS_ERR_NOENT; + + // stat paths + lfsr_stat(&lfs, "espresso/espresso", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/americano", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/macchiato", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/latte", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/cappuccino", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/mocha", &info) => LFS_ERR_NOENT; + + lfsr_stat(&lfs, "coffee/drip", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/coldbrew", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/turkish", &info) => 0; + assert(strcmp(info.name, "turkish") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/tubruk", &info) => 0; + assert(strcmp(info.name, "tubruk") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/vietnamese", &info) => 0; + assert(strcmp(info.name, "vietnamese") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/thai", &info) => 0; + assert(strcmp(info.name, "thai") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfsr_unmount(&lfs) => 0; +''' + +# parent noent tests +[cases.test_paths_noent_parent] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; + lfsr_mount(&lfs, LFS_F_RDWR, CFG) => 0; + + // create paths + lfsr_mkdir(&lfs, "coffee") => 0; + if (DIR) { + lfsr_mkdir(&lfs, "_offee/drip") => LFS_ERR_NOENT; + lfsr_mkdir(&lfs, "c_ffee/coldbrew") => LFS_ERR_NOENT; + lfsr_mkdir(&lfs, "co_fee/turkish") => LFS_ERR_NOENT; + lfsr_mkdir(&lfs, "cof_ee/tubruk") => LFS_ERR_NOENT; + lfsr_mkdir(&lfs, "_coffee/vietnamese") => LFS_ERR_NOENT; + lfsr_mkdir(&lfs, "coffee_/thai") => LFS_ERR_NOENT; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "_offee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "c_ffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "co_fee/turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "cof_ee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "_coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "coffee_/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + } + + // ok, actually create paths + if (DIR) { + lfsr_mkdir(&lfs, "coffee/drip") => 0; + lfsr_mkdir(&lfs, "coffee/coldbrew") => 0; + lfsr_mkdir(&lfs, "coffee/turkish") => 0; + lfsr_mkdir(&lfs, "coffee/tubruk") => 0; + lfsr_mkdir(&lfs, "coffee/vietnamese") => 0; + lfsr_mkdir(&lfs, "coffee/thai") => 0; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + } + + // stat paths + struct lfs_info info; + lfsr_stat(&lfs, "_offee/drip", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "c_ffee/coldbrew", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "co_fee/turkish", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "cof_ee/tubruk", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "_coffee/vietnamese", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee_/thai", &info) => LFS_ERR_NOENT; + + // file open paths, only works on files! + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "_offee/drip", + LFS_O_RDONLY) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "c_ffee/coldbrew", + LFS_O_RDONLY) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "co_fee/turkish", + LFS_O_RDONLY) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "cof_ee/tubruk", + LFS_O_RDONLY) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "_coffee/vietnamese", + LFS_O_RDONLY) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "coffee_/thai", + LFS_O_RDONLY) => LFS_ERR_NOENT; + + lfsr_file_open(&lfs, &file, "_offee/drip", LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOENT; - lfsr_mkdir(&lfs, "milk/cream/foam") => LFS_ERR_NOENT; - lfsr_file_open(&lfs, &file, "milk/cream/foam", + lfsr_file_open(&lfs, &file, "c_ffee/coldbrew", LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "co_fee/turkish", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "cof_ee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "_coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "coffee_/thai", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOENT; + + lfsr_file_open(&lfs, &file, "_offee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "c_ffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "co_fee/turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "cof_ee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "_coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "coffee_/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + + // dir open paths, only works on dirs! + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "_offee/drip") => LFS_ERR_NOENT; + lfsr_dir_open(&lfs, &dir, "c_ffee/coldbrew") => LFS_ERR_NOENT; + lfsr_dir_open(&lfs, &dir, "co_fee/turkish") => LFS_ERR_NOENT; + lfsr_dir_open(&lfs, &dir, "cof_ee/tubruk") => LFS_ERR_NOENT; + lfsr_dir_open(&lfs, &dir, "_coffee/vietnamese") => LFS_ERR_NOENT; + lfsr_dir_open(&lfs, &dir, "coffee_/thai") => LFS_ERR_NOENT; + + // rename paths + lfsr_mkdir(&lfs, "espresso") => 0; + // bad source + lfsr_rename(&lfs, + "_offee/drip", + "espresso/espresso") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "c_ffee/coldbrew", + "espresso/americano") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "co_fee/turkish", + "espresso/macchiato") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "cof_ee/tubruk", + "espresso/latte") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "_coffee/vietnamese", + "espresso/cappuccino") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee_/thai", + "espresso/mocha") => LFS_ERR_NOENT; + + // bad destination + lfsr_rename(&lfs, + "coffee/drip", + "_spresso/espresso") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/coldbrew", + "e_presso/americano") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/turkish", + "es_resso/macchiato") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/tubruk", + "esp_esso/latte") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/vietnamese", + "_espresso/cappuccino") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/thai", + "espresso_/mocha") => LFS_ERR_NOENT; + + // bad source and bad destination + lfsr_rename(&lfs, + "_offee/drip", + "_spresso/espresso") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "c_ffee/coldbrew", + "e_presso/americano") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "co_fee/turkish", + "es_resso/macchiato") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "cof_ee/tubruk", + "esp_esso/latte") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "_coffee/vietnamese", + "_espresso/cappuccino") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee_/thai", + "espresso_/mocha") => LFS_ERR_NOENT; + + // here's a weird one, what happens if our rename is also a noop? + lfsr_rename(&lfs, + "_offee/drip", + "_offee/drip") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "c_ffee/coldbrew", + "c_ffee/coldbrew") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "co_fee/turkish", + "co_fee/turkish") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "cof_ee/tubruk", + "cof_ee/tubruk") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "_coffee/vietnamese", + "_coffee/vietnamese") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee_/thai", + "coffee_/thai") => LFS_ERR_NOENT; + + // remove paths + lfsr_remove(&lfs, "_offee/drip") => LFS_ERR_NOENT; + lfsr_remove(&lfs, "c_ffee/coldbrew") => LFS_ERR_NOENT; + lfsr_remove(&lfs, "co_fee/turkish") => LFS_ERR_NOENT; + lfsr_remove(&lfs, "cof_ee/tubruk") => LFS_ERR_NOENT; + lfsr_remove(&lfs, "_coffee/vietnamese") => LFS_ERR_NOENT; + lfsr_remove(&lfs, "coffee_/thai") => LFS_ERR_NOENT; + + // stat paths + lfsr_stat(&lfs, "espresso/espresso", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/americano", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/macchiato", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/latte", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/cappuccino", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/mocha", &info) => LFS_ERR_NOENT; + + lfsr_stat(&lfs, "coffee/drip", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/coldbrew", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/turkish", &info) => 0; + assert(strcmp(info.name, "turkish") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/tubruk", &info) => 0; + assert(strcmp(info.name, "tubruk") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/vietnamese", &info) => 0; + assert(strcmp(info.name, "vietnamese") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/thai", &info) => 0; + assert(strcmp(info.name, "thai") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfsr_unmount(&lfs) => 0; +''' + +# parent notdir tests +[cases.test_paths_notdir_parent] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; + lfsr_mount(&lfs, LFS_F_RDWR, CFG) => 0; + + // create paths + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + + if (DIR) { + lfsr_mkdir(&lfs, "drip/coffee") => LFS_ERR_NOTDIR; + lfsr_mkdir(&lfs, "coldbrew/coffee") => LFS_ERR_NOTDIR; + lfsr_mkdir(&lfs, "turkish/coffee") => LFS_ERR_NOTDIR; + lfsr_mkdir(&lfs, "tubruk/coffee") => LFS_ERR_NOTDIR; + lfsr_mkdir(&lfs, "vietnamese/coffee") => LFS_ERR_NOTDIR; + lfsr_mkdir(&lfs, "thai/coffee") => LFS_ERR_NOTDIR; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "drip/coffee", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coldbrew/coffee", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "turkish/coffee", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "tubruk/coffee", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "vietnamese/coffee", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "thai/coffee", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + } + + // stat paths + struct lfs_info info; + lfsr_stat(&lfs, "drip/coffee", &info) => LFS_ERR_NOTDIR; + lfsr_stat(&lfs, "coldbrew/coffee", &info) => LFS_ERR_NOTDIR; + lfsr_stat(&lfs, "turkish/coffee", &info) => LFS_ERR_NOTDIR; + lfsr_stat(&lfs, "tubruk/coffee", &info) => LFS_ERR_NOTDIR; + lfsr_stat(&lfs, "vietnamese/coffee", &info) => LFS_ERR_NOTDIR; + lfsr_stat(&lfs, "thai/coffee", &info) => LFS_ERR_NOTDIR; + + // file open paths, only works on files! + lfsr_file_open(&lfs, &file, "drip/coffee", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coldbrew/coffee", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "turkish/coffee", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "tubruk/coffee", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "vietnamese/coffee", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "thai/coffee", + LFS_O_RDONLY) => LFS_ERR_NOTDIR; + + lfsr_file_open(&lfs, &file, "drip/coffee", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coldbrew/coffee", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "turkish/coffee", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "tubruk/coffee", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "vietnamese/coffee", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "thai/coffee", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + + lfsr_file_open(&lfs, &file, "drip/coffee", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coldbrew/coffee", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "turkish/coffee", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "tubruk/coffee", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "vietnamese/coffee", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "thai/coffee", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + + // dir open paths, only works on dirs! + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "drip/coffee") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "coldbrew/coffee") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "turkish/coffee") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "tubruk/coffee") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "vietnamese/coffee") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "thai/coffee") => LFS_ERR_NOTDIR; + + // make some normal paths so we have something to rename + lfsr_mkdir(&lfs, "coffee") => 0; + if (DIR) { + lfsr_mkdir(&lfs, "coffee/drip") => 0; + lfsr_mkdir(&lfs, "coffee/coldbrew") => 0; + lfsr_mkdir(&lfs, "coffee/turkish") => 0; + lfsr_mkdir(&lfs, "coffee/tubruk") => 0; + lfsr_mkdir(&lfs, "coffee/vietnamese") => 0; + lfsr_mkdir(&lfs, "coffee/thai") => 0; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + } + + // rename paths + lfsr_mkdir(&lfs, "espresso") => 0; + // bad source + lfsr_rename(&lfs, + "drip/coffee", + "espresso/espresso") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "coldbrew/coffee", + "espresso/americano") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "turkish/coffee", + "espresso/macchiato") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "tubruk/coffee", + "espresso/latte") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "vietnamese/coffee", + "espresso/cappuccino") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "thai/coffee", + "espresso/mocha") => LFS_ERR_NOTDIR; + + // bad destination + lfsr_rename(&lfs, + "coffee/drip", + "drip/espresso") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "coffee/coldbrew", + "coldbrew/espresso") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "coffee/turkish", + "turkish/espresso") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "coffee/tubruk", + "tubruk/espresso") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "coffee/vietnamese", + "vietnamese/espresso") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "coffee/thai", + "thai/espresso") => LFS_ERR_NOTDIR; + + // bad source and bad destination + lfsr_rename(&lfs, + "drip/coffee", + "drip/espresso") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "coldbrew/coffee", + "coldbrew/espresso") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "turkish/coffee", + "turkish/espresso") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "tubruk/coffee", + "tubruk/espresso") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "vietnamese/coffee", + "vietnamese/espresso") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "thai/coffee", + "thai/espresso") => LFS_ERR_NOTDIR; + + // here's a weird one, what happens if our rename is also a noop? + lfsr_rename(&lfs, + "drip/coffee", + "drip/coffee") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "coldbrew/coffee", + "coldbrew/coffee") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "turkish/coffee", + "turkish/coffee") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "tubruk/coffee", + "tubruk/coffee") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "vietnamese/coffee", + "vietnamese/coffee") => LFS_ERR_NOTDIR; + lfsr_rename(&lfs, + "thai/coffee", + "thai/coffee") => LFS_ERR_NOTDIR; + + // remove paths + lfsr_stat(&lfs, "drip/espresso", &info) => LFS_ERR_NOTDIR; + lfsr_stat(&lfs, "coldbrew/espresso", &info) => LFS_ERR_NOTDIR; + lfsr_stat(&lfs, "turkish/espresso", &info) => LFS_ERR_NOTDIR; + lfsr_stat(&lfs, "tubruk/espresso", &info) => LFS_ERR_NOTDIR; + lfsr_stat(&lfs, "vietnamese/espresso", &info) => LFS_ERR_NOTDIR; + lfsr_stat(&lfs, "thai/espresso", &info) => LFS_ERR_NOTDIR; + + // stat paths + lfsr_stat(&lfs, "drip/espresso", &info) => LFS_ERR_NOTDIR; + lfsr_stat(&lfs, "coldbrew/espresso", &info) => LFS_ERR_NOTDIR; + lfsr_stat(&lfs, "turkish/espresso", &info) => LFS_ERR_NOTDIR; + lfsr_stat(&lfs, "tubruk/espresso", &info) => LFS_ERR_NOTDIR; + lfsr_stat(&lfs, "vietnamese/espresso", &info) => LFS_ERR_NOTDIR; + lfsr_stat(&lfs, "thai/espresso", &info) => LFS_ERR_NOTDIR; + + lfsr_stat(&lfs, "coffee/drip", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/coldbrew", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/turkish", &info) => 0; + assert(strcmp(info.name, "turkish") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/tubruk", &info) => 0; + assert(strcmp(info.name, "tubruk") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/vietnamese", &info) => 0; + assert(strcmp(info.name, "vietnamese") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/thai", &info) => 0; + assert(strcmp(info.name, "thai") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfsr_unmount(&lfs) => 0; +''' + +# noent tests with trailing slashes +[cases.test_paths_noent_trailing_slashes] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; + lfsr_mount(&lfs, LFS_F_RDWR, CFG) => 0; + + // create paths + lfsr_mkdir(&lfs, "coffee") => 0; + if (DIR) { + lfsr_mkdir(&lfs, "coffee/drip") => 0; + lfsr_mkdir(&lfs, "coffee/coldbrew") => 0; + lfsr_mkdir(&lfs, "coffee/turkish") => 0; + lfsr_mkdir(&lfs, "coffee/tubruk") => 0; + lfsr_mkdir(&lfs, "coffee/vietnamese") => 0; + lfsr_mkdir(&lfs, "coffee/thai") => 0; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + } + + // stat paths + struct lfs_info info; + lfsr_stat(&lfs, "coffee/_rip//////", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/c_ldbrew/////", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/tu_kish////", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/tub_uk///", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/_vietnamese//", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/thai_/", &info) => LFS_ERR_NOENT; + + // file open paths, only works on files! + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "coffee/_rip/", + LFS_O_RDONLY) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "coffee/c_ldbrew//", + LFS_O_RDONLY) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "coffee/tu_kish///", + LFS_O_RDONLY) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "coffee/tub_uk////", + LFS_O_RDONLY) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "coffee/_vietnamese/////", + LFS_O_RDONLY) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "coffee/thai_//////", + LFS_O_RDONLY) => LFS_ERR_NOENT; + + lfsr_file_open(&lfs, &file, "coffee/_rip/", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/c_ldbrew//", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/tu_kish///", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/tub_uk////", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/_vietnamese/////", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/thai_//////", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOTDIR; + + lfsr_file_open(&lfs, &file, "coffee/_rip/", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/c_ldbrew//", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/tu_kish///", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/tub_uk////", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/_vietnamese/////", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + lfsr_file_open(&lfs, &file, "coffee/thai_//////", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOTDIR; + + // dir open paths, only works on dirs! + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "coffee/_rip/") => LFS_ERR_NOENT; + lfsr_dir_open(&lfs, &dir, "coffee/c_ldbrew//") => LFS_ERR_NOENT; + lfsr_dir_open(&lfs, &dir, "coffee/tu_kish///") => LFS_ERR_NOENT; + lfsr_dir_open(&lfs, &dir, "coffee/tub_uk////") => LFS_ERR_NOENT; + lfsr_dir_open(&lfs, &dir, "coffee/_vietnamese/////") => LFS_ERR_NOENT; + lfsr_dir_open(&lfs, &dir, "coffee/thai_//////") => LFS_ERR_NOENT; + + // rename paths + lfsr_mkdir(&lfs, "espresso") => 0; + // bad source + lfsr_rename(&lfs, + "coffee/_rip//////", + "espresso/espresso") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/c_ldbrew/////", + "espresso/americano") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/tu_kish////", + "espresso/macchiato") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/tub_uk///", + "espresso/latte") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/_vietnamese//", + "espresso/cappuccino") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/thai_/", + "espresso/mocha") => LFS_ERR_NOENT; + + // bad destination + lfsr_rename(&lfs, + "coffee/_rip", + "espresso/espresso/") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/c_ldbrew", + "espresso/americano//") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/tu_kish", + "espresso/macchiato///") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/tub_uk", + "espresso/latte////") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/_vietnamese", + "espresso/cappuccino/////") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/thai_", + "espresso/mocha//////") => LFS_ERR_NOENT; + + // bad source and bad destination + lfsr_rename(&lfs, + "coffee/_rip//////", + "espresso/espresso/") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/c_ldbrew/////", + "espresso/americano//") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/tu_kish////", + "espresso/macchiato///") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/tub_uk///", + "espresso/latte////") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/_vietnamese//", + "espresso/cappuccino/////") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/thai_/", + "espresso/mocha//////") => LFS_ERR_NOENT; + + // here's a weird one, what happens if our rename is also a noop? + lfsr_rename(&lfs, + "coffee/_rip//////", + "coffee/_rip//////") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/c_ldbrew/////", + "coffee/c_ldbrew/////") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/tu_kish////", + "coffee/tu_kish////") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/tub_uk///", + "coffee/tub_uk///") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/_vietnamese//", + "coffee/_vietnamese//") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/thai_/", + "coffee/thai_/") => LFS_ERR_NOENT; + + // remove paths + lfsr_remove(&lfs, "coffee/_rip/") => LFS_ERR_NOENT; + lfsr_remove(&lfs, "coffee/c_ldbrew//") => LFS_ERR_NOENT; + lfsr_remove(&lfs, "coffee/tu_kish///") => LFS_ERR_NOENT; + lfsr_remove(&lfs, "coffee/tub_uk////") => LFS_ERR_NOENT; + lfsr_remove(&lfs, "coffee/_vietnamese/////") => LFS_ERR_NOENT; + lfsr_remove(&lfs, "coffee/thai_//////") => LFS_ERR_NOENT; + + // stat paths + lfsr_stat(&lfs, "espresso/espresso", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/americano", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/macchiato", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/latte", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/cappuccino", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/mocha", &info) => LFS_ERR_NOENT; + + lfsr_stat(&lfs, "coffee/drip", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/coldbrew", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/turkish", &info) => 0; + assert(strcmp(info.name, "turkish") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/tubruk", &info) => 0; + assert(strcmp(info.name, "tubruk") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/vietnamese", &info) => 0; + assert(strcmp(info.name, "vietnamese") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/thai", &info) => 0; + assert(strcmp(info.name, "thai") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfsr_unmount(&lfs) => 0; +''' + +# noent tests with trailing dots +[cases.test_paths_noent_trailing_dots] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; + lfsr_mount(&lfs, LFS_F_RDWR, CFG) => 0; + + // create paths + lfsr_mkdir(&lfs, "coffee") => 0; + if (DIR) { + lfsr_mkdir(&lfs, "coffee/drip") => 0; + lfsr_mkdir(&lfs, "coffee/coldbrew") => 0; + lfsr_mkdir(&lfs, "coffee/turkish") => 0; + lfsr_mkdir(&lfs, "coffee/tubruk") => 0; + lfsr_mkdir(&lfs, "coffee/vietnamese") => 0; + lfsr_mkdir(&lfs, "coffee/thai") => 0; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + } + + // stat paths + struct lfs_info info; + lfsr_stat(&lfs, "coffee/_rip/./././././.", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/c_ldbrew/././././.", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/tu_kish/./././.", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/tub_uk/././.", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/_vietnamese/./.", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/thai_/.", &info) => LFS_ERR_NOENT; + + // file open paths, only works on files! + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "coffee/_rip/.", + LFS_O_RDONLY) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "coffee/c_ldbrew/./.", + LFS_O_RDONLY) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "coffee/tu_kish/././.", + LFS_O_RDONLY) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "coffee/tub_uk/./././.", + LFS_O_RDONLY) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "coffee/_vietnamese/././././.", + LFS_O_RDONLY) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "coffee/thai_/./././././.", + LFS_O_RDONLY) => LFS_ERR_NOENT; + + lfsr_file_open(&lfs, &file, "coffee/_rip/.", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "coffee/c_ldbrew/./.", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "coffee/tu_kish/././.", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "coffee/tub_uk/./././.", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "coffee/_vietnamese/././././.", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "coffee/thai_/./././././.", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NOENT; + + lfsr_file_open(&lfs, &file, "coffee/_rip/.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "coffee/c_ldbrew/./.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "coffee/tu_kish/././.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "coffee/tub_uk/./././.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "coffee/_vietnamese/././././.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + lfsr_file_open(&lfs, &file, "coffee/thai_/./././././.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NOENT; + + // dir open paths, only works on dirs! + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "coffee/_rip/.") => LFS_ERR_NOENT; + lfsr_dir_open(&lfs, &dir, "coffee/c_ldbrew/./.") => LFS_ERR_NOENT; + lfsr_dir_open(&lfs, &dir, "coffee/tu_kish/././.") => LFS_ERR_NOENT; + lfsr_dir_open(&lfs, &dir, "coffee/tub_uk/./././.") => LFS_ERR_NOENT; + lfsr_dir_open(&lfs, &dir, "coffee/_vietnamese/././././.") => LFS_ERR_NOENT; + lfsr_dir_open(&lfs, &dir, "coffee/thai_/./././././.") => LFS_ERR_NOENT; + + // rename paths + lfsr_mkdir(&lfs, "espresso") => 0; + // bad source + lfsr_rename(&lfs, + "coffee/_rip/./././././.", + "espresso/espresso") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/c_ldbrew/././././.", + "espresso/americano") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/tu_kish/./././.", + "espresso/macchiato") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/tub_uk/././.", + "espresso/latte") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/_vietnamese/./.", + "espresso/cappuccino") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/thai_/.", + "espresso/mocha") => LFS_ERR_NOENT; + + // bad destination + lfsr_rename(&lfs, + "coffee/_rip", + "espresso/espresso/.") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/c_ldbrew", + "espresso/americano/./.") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/tu_kish", + "espresso/macchiato/././.") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/tub_uk", + "espresso/latte/./././.") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/_vietnamese", + "espresso/cappuccino/././././.") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/thai_", + "espresso/mocha/./././././.") => LFS_ERR_NOENT; + + // bad source and bad destination + lfsr_rename(&lfs, + "coffee/_rip/./././././.", + "espresso/espresso/.") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/c_ldbrew/././././.", + "espresso/americano/./.") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/tu_kish/./././.", + "espresso/macchiato/././.") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/tub_uk/././.", + "espresso/latte/./././.") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/_vietnamese/./.", + "espresso/cappuccino/././././.") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/thai_/.", + "espresso/mocha/./././././.") => LFS_ERR_NOENT; + + // here's a weird one, what happens if our rename is also a noop? + lfsr_rename(&lfs, + "coffee/_rip/./././././.", + "coffee/_rip/./././././.") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/c_ldbrew/././././.", + "coffee/c_ldbrew/././././.") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/tu_kish/./././.", + "coffee/tu_kish/./././.") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/tub_uk/././.", + "coffee/tub_uk/././.") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/_vietnamese/./.", + "coffee/_vietnamese/./.") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/thai_/.", + "coffee/thai_/.") => LFS_ERR_NOENT; + + // remove paths + lfsr_remove(&lfs, "coffee/_rip/.") => LFS_ERR_NOENT; + lfsr_remove(&lfs, "coffee/c_ldbrew/./.") => LFS_ERR_NOENT; + lfsr_remove(&lfs, "coffee/tu_kish/././.") => LFS_ERR_NOENT; + lfsr_remove(&lfs, "coffee/tub_uk/./././.") => LFS_ERR_NOENT; + lfsr_remove(&lfs, "coffee/_vietnamese/././././.") => LFS_ERR_NOENT; + lfsr_remove(&lfs, "coffee/thai_/./././././.") => LFS_ERR_NOENT; + + // stat paths + lfsr_stat(&lfs, "espresso/espresso", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/americano", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/macchiato", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/latte", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/cappuccino", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/mocha", &info) => LFS_ERR_NOENT; + + lfsr_stat(&lfs, "coffee/drip", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/coldbrew", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/turkish", &info) => 0; + assert(strcmp(info.name, "turkish") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/tubruk", &info) => 0; + assert(strcmp(info.name, "tubruk") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/vietnamese", &info) => 0; + assert(strcmp(info.name, "vietnamese") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/thai", &info) => 0; + assert(strcmp(info.name, "thai") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfsr_unmount(&lfs) => 0; +''' + +# noent tests with trailing dotdots +[cases.test_paths_noent_trailing_dotdots] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; + lfsr_mount(&lfs, LFS_F_RDWR, CFG) => 0; + + // create paths + lfsr_mkdir(&lfs, "coffee") => 0; + if (DIR) { + lfsr_mkdir(&lfs, "coffee/drip") => 0; + lfsr_mkdir(&lfs, "coffee/coldbrew") => 0; + lfsr_mkdir(&lfs, "coffee/turkish") => 0; + lfsr_mkdir(&lfs, "coffee/tubruk") => 0; + lfsr_mkdir(&lfs, "coffee/vietnamese") => 0; + lfsr_mkdir(&lfs, "coffee/thai") => 0; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/turkish", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/tubruk", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/vietnamese", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/thai", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + } + + // stat paths + struct lfs_info info; + lfsr_stat(&lfs, "coffee/_rip/../../../../../..", &info) => LFS_ERR_INVAL; + lfsr_stat(&lfs, "coffee/c_ldbrew/../../../../..", &info) => LFS_ERR_INVAL; + lfsr_stat(&lfs, "coffee/tu_kish/../../../..", &info) => LFS_ERR_INVAL; + lfsr_stat(&lfs, "coffee/tub_uk/../../..", &info) => LFS_ERR_INVAL; + lfsr_stat(&lfs, "coffee/_vietnamese/../..", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); + lfsr_stat(&lfs, "coffee/thai_/..", &info) => 0; + assert(strcmp(info.name, "coffee") == 0); + assert(info.type == LFS_TYPE_DIR); + + // file open paths, only works on files! + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "coffee/_rip/..", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/c_ldbrew/../..", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/tu_kish/../../..", + LFS_O_RDONLY) => LFS_ERR_INVAL; + lfsr_file_open(&lfs, &file, "coffee/tub_uk/../../../..", + LFS_O_RDONLY) => LFS_ERR_INVAL; + lfsr_file_open(&lfs, &file, "coffee/_vietnamese/../../../../..", + LFS_O_RDONLY) => LFS_ERR_INVAL; + lfsr_file_open(&lfs, &file, "coffee/thai_/../../../../../..", + LFS_O_RDONLY) => LFS_ERR_INVAL; + + // dir open paths, only works on dirs! + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "coffee/_rip/..") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "coffee/c_ldbrew/../..") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "coffee/tu_kish/../../..") => LFS_ERR_INVAL; + lfsr_dir_open(&lfs, &dir, "coffee/tub_uk/../../../..") => LFS_ERR_INVAL; + lfsr_dir_open(&lfs, &dir, "coffee/_vietnamese/../../../../..") => LFS_ERR_INVAL; + lfsr_dir_open(&lfs, &dir, "coffee/thai_/../../../../../..") => LFS_ERR_INVAL; + + // rename paths + lfsr_mkdir(&lfs, "espresso") => 0; + // bad source + lfsr_rename(&lfs, + "coffee/_rip/../../../../../..", + "espresso/espresso") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "coffee/c_ldbrew/../../../../..", + "espresso/americano") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "coffee/tu_kish/../../../..", + "espresso/macchiato") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "coffee/tub_uk/../../..", + "espresso/latte") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "coffee/_vietnamese/../..", + "espresso/cappuccino") => LFS_ERR_INVAL; + // this one works + lfsr_rename(&lfs, + "coffee/thai_/..", + "espresso/mocha") => 0; + lfsr_rename(&lfs, + "espresso/mocha", + "coffee") => 0; + + // bad destination + lfsr_rename(&lfs, + "coffee/_rip", + "espresso/espresso/..") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/c_ldbrew", + "espresso/americano/../..") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/tu_kish", + "espresso/macchiato/../../..") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/tub_uk", + "espresso/latte/../../../..") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/_vietnamese", + "espresso/cappuccino/../../../../..") => LFS_ERR_NOENT; + lfsr_rename(&lfs, + "coffee/thai_", + "espresso/mocha/../../../../../..") => LFS_ERR_NOENT; + + // bad source and bad destination + lfsr_rename(&lfs, + "coffee/_rip/../../../../../..", + "espresso/espresso/..") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "coffee/c_ldbrew/../../../../..", + "espresso/americano/../..") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "coffee/tu_kish/../../../..", + "espresso/macchiato/../../..") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "coffee/tub_uk/../../..", + "espresso/latte/../../../..") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "coffee/_vietnamese/../..", + "espresso/cappuccino/../../../../..") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "coffee/thai_/..", + "espresso/mocha/../../../../../..") => LFS_ERR_INVAL; + + // here's a weird one, what happens if our rename is also a noop? + lfsr_rename(&lfs, + "coffee/_rip/../../../../../..", + "coffee/_rip/../../../../../..") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "coffee/c_ldbrew/../../../../..", + "coffee/c_ldbrew/../../../../..") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "coffee/tu_kish/../../../..", + "coffee/tu_kish/../../../..") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "coffee/tub_uk/../../..", + "coffee/tub_uk/../../..") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "coffee/_vietnamese/../..", + "coffee/_vietnamese/../..") => LFS_ERR_INVAL; + lfsr_rename(&lfs, + "coffee/thai_/..", + "coffee/thai_/..") => 0; + + // remove paths + lfsr_remove(&lfs, "coffee/_rip/..") => LFS_ERR_NOTEMPTY; + lfsr_remove(&lfs, "coffee/c_ldbrew/../..") => LFS_ERR_INVAL; + lfsr_remove(&lfs, "coffee/tu_kish/../../..") => LFS_ERR_INVAL; + lfsr_remove(&lfs, "coffee/tub_uk/../../../..") => LFS_ERR_INVAL; + lfsr_remove(&lfs, "coffee/_vietnamese/../../../../..") => LFS_ERR_INVAL; + lfsr_remove(&lfs, "coffee/thai_/../../../../../..") => LFS_ERR_INVAL; + + // stat paths + lfsr_stat(&lfs, "espresso/espresso", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/americano", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/macchiato", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/latte", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/cappuccino", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "espresso/mocha", &info) => LFS_ERR_NOENT; + + lfsr_stat(&lfs, "coffee/drip", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/coldbrew", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/turkish", &info) => 0; + assert(strcmp(info.name, "turkish") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/tubruk", &info) => 0; + assert(strcmp(info.name, "tubruk") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/vietnamese", &info) => 0; + assert(strcmp(info.name, "vietnamese") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/thai", &info) => 0; + assert(strcmp(info.name, "thai") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfsr_unmount(&lfs) => 0; +''' + +# test an empty path, this should error +[cases.test_paths_empty] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; + lfsr_mount(&lfs, LFS_F_RDWR, CFG) => 0; + struct lfs_info info; + + // create empty, this should error + if (DIR) { + lfsr_mkdir(&lfs, "") => LFS_ERR_INVAL; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_INVAL; + } + + // stat empty + lfsr_stat(&lfs, "", &info) => LFS_ERR_INVAL; + + // file open empty, only works on files! + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "", + LFS_O_RDONLY) => LFS_ERR_INVAL; + + lfsr_file_open(&lfs, &file, "", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_INVAL; + + lfsr_file_open(&lfs, &file, "", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_INVAL; + + // dir open empty, only works on dirs! + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "") => LFS_ERR_INVAL; + + // rename empty, this should error + lfsr_rename(&lfs, "", "coffee") => LFS_ERR_INVAL; + + lfsr_mkdir(&lfs, "coffee") => 0; + lfsr_rename(&lfs, "coffee", "") => LFS_ERR_INVAL; + lfsr_remove(&lfs, "coffee") => 0; + + lfsr_rename(&lfs, "", "") => LFS_ERR_INVAL; + + // stat empty + lfsr_stat(&lfs, "", &info) => LFS_ERR_INVAL; + + // remove empty, this should error + lfsr_remove(&lfs, "") => LFS_ERR_INVAL; + + // stat empty + lfsr_stat(&lfs, "", &info) => LFS_ERR_INVAL; + lfsr_unmount(&lfs) => 0; ''' # root operations +# +# POSIX deviations: +# +# - Root modifications return EINVAL instead of EBUSY: +# - littlefs: remove("/") => EINVAL +# - POSIX: remove("/") => EBUSY +# Reason: This would be the only use of EBUSY in the system. +# [cases.test_paths_root] +defines.DIR = [false, true] code = ''' lfs_t lfs; lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; + lfsr_mount(&lfs, LFS_F_RDWR, CFG) => 0; struct lfs_info info; + + // create root, this should error + if (DIR) { + lfsr_mkdir(&lfs, "/") => LFS_ERR_EXIST; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "/", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + } + + // stat root lfsr_stat(&lfs, "/", &info) => 0; assert(strcmp(info.name, "/") == 0); assert(info.type == LFS_TYPE_DIR); - assert(info.size == 0); - lfsr_mkdir(&lfs, "/") => LFS_ERR_EXIST; + // file open root, only works on files! lfsr_file_t file; + lfsr_file_open(&lfs, &file, "/", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/", LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; - lfsr_remove(&lfs, "/") => LFS_ERR_INVAL; - lfsr_unmount(&lfs) => 0; -''' + lfsr_file_open(&lfs, &file, "/", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; -# root representations -[cases.test_paths_root_reprs] -code = ''' - lfs_t lfs; - lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; - struct lfs_info info; + // dir open root, only works on dirs! + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "/") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + + // rename root, this should error + lfsr_rename(&lfs, "/", "coffee") => LFS_ERR_INVAL; + + lfsr_mkdir(&lfs, "coffee") => 0; + lfsr_rename(&lfs, "coffee", "/") => LFS_ERR_INVAL; + lfsr_remove(&lfs, "coffee") => 0; + + lfsr_rename(&lfs, "/", "/") => LFS_ERR_INVAL; + + // stat root lfsr_stat(&lfs, "/", &info) => 0; assert(strcmp(info.name, "/") == 0); assert(info.type == LFS_TYPE_DIR); - assert(info.size == 0); - lfsr_stat(&lfs, "", &info) => 0; + + // remove root, this should error + lfsr_remove(&lfs, "/") => LFS_ERR_INVAL; + + // stat root + lfsr_stat(&lfs, "/", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); + + lfsr_unmount(&lfs) => 0; +''' + +# other root representations +[cases.test_paths_root_aliases] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; + lfsr_mount(&lfs, LFS_F_RDWR, CFG) => 0; + struct lfs_info info; + + // create root, this should error + if (DIR) { + lfsr_mkdir(&lfs, "/") => LFS_ERR_EXIST; + lfsr_mkdir(&lfs, ".") => LFS_ERR_EXIST; + lfsr_mkdir(&lfs, "./") => LFS_ERR_EXIST; + lfsr_mkdir(&lfs, "/.") => LFS_ERR_EXIST; + lfsr_mkdir(&lfs, "//") => LFS_ERR_EXIST; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "/", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, ".", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "./", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/.", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "//", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + } + + // stat root + lfsr_stat(&lfs, "/", &info) => 0; assert(strcmp(info.name, "/") == 0); assert(info.type == LFS_TYPE_DIR); - assert(info.size == 0); lfsr_stat(&lfs, ".", &info) => 0; assert(strcmp(info.name, "/") == 0); assert(info.type == LFS_TYPE_DIR); - assert(info.size == 0); - lfsr_stat(&lfs, "..", &info) => 0; - assert(strcmp(info.name, "/") == 0); - assert(info.type == LFS_TYPE_DIR); - assert(info.size == 0); - lfsr_stat(&lfs, "//", &info) => 0; - assert(strcmp(info.name, "/") == 0); - assert(info.type == LFS_TYPE_DIR); - assert(info.size == 0); lfsr_stat(&lfs, "./", &info) => 0; assert(strcmp(info.name, "/") == 0); assert(info.type == LFS_TYPE_DIR); - assert(info.size == 0); + lfsr_stat(&lfs, "/.", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); + lfsr_stat(&lfs, "//", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); + + // file open root, only works on files! + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "/", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, ".", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "./", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/.", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "//", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + + lfsr_file_open(&lfs, &file, "/", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, ".", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "./", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "/.", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "//", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfsr_file_open(&lfs, &file, "/", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, ".", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "./", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "/.", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "//", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + + // dir open root, only works on dirs! + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "/") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, ".") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "./") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "/.") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "//") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + + // rename root, this should error + lfsr_rename(&lfs, "/", "coffee") => LFS_ERR_INVAL; + lfsr_rename(&lfs, ".", "coffee") => LFS_ERR_INVAL; + lfsr_rename(&lfs, "./", "coffee") => LFS_ERR_INVAL; + lfsr_rename(&lfs, "/.", "coffee") => LFS_ERR_INVAL; + lfsr_rename(&lfs, "//", "coffee") => LFS_ERR_INVAL; + + lfsr_mkdir(&lfs, "coffee") => 0; + lfsr_rename(&lfs, "coffee", "/") => LFS_ERR_INVAL; + lfsr_rename(&lfs, "coffee", ".") => LFS_ERR_INVAL; + lfsr_rename(&lfs, "coffee", "./") => LFS_ERR_INVAL; + lfsr_rename(&lfs, "coffee", "/.") => LFS_ERR_INVAL; + lfsr_rename(&lfs, "coffee", "//") => LFS_ERR_INVAL; + lfsr_remove(&lfs, "coffee") => 0; + + lfsr_rename(&lfs, "/", "/") => LFS_ERR_INVAL; + lfsr_rename(&lfs, ".", ".") => LFS_ERR_INVAL; + lfsr_rename(&lfs, "..", "..") => LFS_ERR_INVAL; + lfsr_rename(&lfs, "./", "./") => LFS_ERR_INVAL; + lfsr_rename(&lfs, "/.", "/.") => LFS_ERR_INVAL; + lfsr_rename(&lfs, "//", "//") => LFS_ERR_INVAL; + + // stat root + lfsr_stat(&lfs, "/", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); + lfsr_stat(&lfs, ".", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); + lfsr_stat(&lfs, "./", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); + lfsr_stat(&lfs, "/.", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); + lfsr_stat(&lfs, "//", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); + + // remove root, this should error + lfsr_remove(&lfs, "/") => LFS_ERR_INVAL; + lfsr_remove(&lfs, ".") => LFS_ERR_INVAL; + lfsr_remove(&lfs, "./") => LFS_ERR_INVAL; + lfsr_remove(&lfs, "/.") => LFS_ERR_INVAL; + lfsr_remove(&lfs, "//") => LFS_ERR_INVAL; + + // stat root + lfsr_stat(&lfs, "/", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); + lfsr_stat(&lfs, ".", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); + lfsr_stat(&lfs, "./", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); + lfsr_stat(&lfs, "/.", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); + lfsr_stat(&lfs, "//", &info) => 0; + assert(strcmp(info.name, "/") == 0); + assert(info.type == LFS_TYPE_DIR); + lfsr_unmount(&lfs) => 0; ''' -# max path test -[cases.test_paths_max] +# superblock magic shouldn't appear as a file +[cases.test_paths_magic_noent] code = ''' lfs_t lfs; lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; - lfsr_mkdir(&lfs, "coffee") => 0; - lfsr_mkdir(&lfs, "coffee/drip") => 0; - lfsr_mkdir(&lfs, "coffee/espresso") => 0; - lfsr_mkdir(&lfs, "coffee/coldbrew") => 0; + lfsr_mount(&lfs, LFS_F_RDWR, CFG) => 0; - char path[2*LFS_NAME_MAX+2]; - memset(path, 'w', LFS_NAME_MAX+1); - path[LFS_NAME_MAX+1] = '\0'; - lfsr_mkdir(&lfs, path) => LFS_ERR_NAMETOOLONG; + // stat littlefs, which shouldn't exist + struct lfs_info info; + lfsr_stat(&lfs, "littlefs", &info) => LFS_ERR_NOENT; + + // file open littlefs, which shouldn't exist lfsr_file_t file; - lfsr_file_open(&lfs, &file, path, - LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NAMETOOLONG; + lfsr_file_open(&lfs, &file, "littlefs", + LFS_O_RDONLY) => LFS_ERR_NOENT; + + // dir open littlefs, which shouldn't exist + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "littlefs") => LFS_ERR_NOENT; + + // rename littlefs, which shouldn't exist + lfsr_rename(&lfs, "littlefs", "coffee") => LFS_ERR_NOENT; + + // remove littlefs, which shouldn't exist + lfsr_remove(&lfs, "littlefs") => LFS_ERR_NOENT; + + // stat littlefs, which shouldn't exist + lfsr_stat(&lfs, "coffee", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "littlefs", &info) => LFS_ERR_NOENT; - memcpy(path, "coffee/", strlen("coffee/")); - memset(path+strlen("coffee/"), 'w', LFS_NAME_MAX+1); - path[strlen("coffee/")+LFS_NAME_MAX+1] = '\0'; - lfsr_mkdir(&lfs, path) => LFS_ERR_NAMETOOLONG; - lfsr_file_open(&lfs, &file, path, - LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_NAMETOOLONG; lfsr_unmount(&lfs) => 0; ''' -# really big path test -[cases.test_paths_really_big] +# superblock magic shouldn't conflict with files, that would be silly +[cases.test_paths_magic_conflict] +defines.DIR = [false, true] code = ''' lfs_t lfs; lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; - lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; - lfsr_mkdir(&lfs, "coffee") => 0; - lfsr_mkdir(&lfs, "coffee/drip") => 0; - lfsr_mkdir(&lfs, "coffee/espresso") => 0; - lfsr_mkdir(&lfs, "coffee/coldbrew") => 0; + lfsr_mount(&lfs, LFS_F_RDWR, CFG) => 0; - char path[2*LFS_NAME_MAX+2]; - memset(path, 'w', LFS_NAME_MAX); - path[LFS_NAME_MAX] = '\0'; - lfsr_mkdir(&lfs, path) => 0; - lfsr_remove(&lfs, path) => 0; - lfsr_file_t file; - lfsr_file_open(&lfs, &file, path, - LFS_O_WRONLY | LFS_O_CREAT) => 0; - lfsr_file_close(&lfs, &file) => 0; - lfsr_remove(&lfs, path) => 0; + // create littlefs + if (DIR) { + lfsr_mkdir(&lfs, "littlefs") => 0; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "littlefs", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + } + + // stat littlefs + struct lfs_info info; + lfsr_stat(&lfs, "littlefs", &info) => 0; + assert(strcmp(info.name, "littlefs") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + // file open littlefs, only works on files! + if (DIR) { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "littlefs", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + + lfsr_file_open(&lfs, &file, "littlefs", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfsr_file_open(&lfs, &file, "littlefs", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "littlefs", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + + lfsr_file_open(&lfs, &file, "littlefs", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + + lfsr_file_open(&lfs, &file, "littlefs", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + } + + // dir open littlefs, only works on dirs! + if (DIR) { + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "littlefs") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + } else { + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "littlefs") => LFS_ERR_NOTDIR; + } + + // rename littlefs + lfsr_rename(&lfs, "littlefs", "coffee") => 0; + lfsr_rename(&lfs, "coffee", "littlefs") => 0; + + // stat littlefs + lfsr_stat(&lfs, "littlefs", &info) => 0; + assert(strcmp(info.name, "littlefs") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfsr_stat(&lfs, "coffee", &info) => LFS_ERR_NOENT; + + // remove littlefs + lfsr_remove(&lfs, "littlefs") => 0; + + // stat littlefs + lfsr_stat(&lfs, "littlefs", &info) => LFS_ERR_NOENT; - memcpy(path, "coffee/", strlen("coffee/")); - memset(path+strlen("coffee/"), 'w', LFS_NAME_MAX); - path[strlen("coffee/")+LFS_NAME_MAX] = '\0'; - lfsr_mkdir(&lfs, path) => 0; - lfsr_remove(&lfs, path) => 0; - lfsr_file_open(&lfs, &file, path, - LFS_O_WRONLY | LFS_O_CREAT) => 0; - lfsr_file_close(&lfs, &file) => 0; - lfsr_remove(&lfs, path) => 0; lfsr_unmount(&lfs) => 0; ''' +# test name too long +[cases.test_paths_nametoolong] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; + lfsr_mount(&lfs, LFS_F_RDWR, CFG) => 0; + + char a_name[512]; + memset(a_name, 'a', LFS_NAME_MAX+1); + a_name[LFS_NAME_MAX+1] = '\0'; + + // create names that are too long, should error + char path[1024]; + lfsr_mkdir(&lfs, "coffee") => 0; + if (DIR) { + sprintf(path, "coffee/%s", a_name); + lfsr_mkdir(&lfs, path) => LFS_ERR_NAMETOOLONG; + } else { + lfsr_file_t file; + sprintf(path, "coffee/%s", a_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_NAMETOOLONG; + } + + // stat paths + struct lfs_info info; + sprintf(path, "coffee/%s", a_name); + lfsr_stat(&lfs, path, &info) => LFS_ERR_NOENT; + + // file open paths, only works on files! + lfsr_file_t file; + sprintf(path, "coffee/%s", a_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_RDONLY) => LFS_ERR_NOENT; + + // dir open paths, only works on dirs! + lfsr_dir_t dir; + sprintf(path, "coffee/%s", a_name); + lfsr_dir_open(&lfs, &dir, path) => LFS_ERR_NOENT; + + // rename paths + lfsr_mkdir(&lfs, "espresso") => 0; + sprintf(path, "coffee/%s", a_name); + lfsr_rename(&lfs, path, "espresso/espresso") => LFS_ERR_NOENT; + + // renaming with too long a destination is tricky! + if (DIR) { + lfsr_mkdir(&lfs, "coffee/drip") => 0; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "coffee/drip", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + } + + sprintf(path, "espresso/%s", a_name); + lfsr_rename(&lfs, "coffee/drip", path) => LFS_ERR_NAMETOOLONG; + + // stat paths + lfsr_stat(&lfs, "coffee/drip", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + sprintf(path, "espresso/%s", a_name); + lfsr_stat(&lfs, path, &info) => LFS_ERR_NOENT; + + // remove paths + sprintf(path, "espresso/%s", a_name); + lfsr_remove(&lfs, path) => LFS_ERR_NOENT; + + // stat paths + lfsr_stat(&lfs, "coffee/drip", &info) => 0; + assert(strcmp(info.name, "drip") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + sprintf(path, "espresso/%s", a_name); + lfsr_stat(&lfs, path, &info) => LFS_ERR_NOENT; + + lfsr_unmount(&lfs) => 0; +''' + +# test name really long but not too long +[cases.test_paths_namejustlongenough] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; + lfsr_mount(&lfs, LFS_F_RDWR, CFG) => 0; + + char a_name[512]; + memset(a_name, 'a', LFS_NAME_MAX); + a_name[LFS_NAME_MAX] = '\0'; + char b_name[512]; + memset(b_name, 'b', LFS_NAME_MAX); + b_name[LFS_NAME_MAX] = '\0'; + char c_name[512]; + memset(c_name, 'c', LFS_NAME_MAX); + c_name[LFS_NAME_MAX] = '\0'; + char d_name[512]; + memset(d_name, 'd', LFS_NAME_MAX); + d_name[LFS_NAME_MAX] = '\0'; + char e_name[512]; + memset(e_name, 'e', LFS_NAME_MAX); + e_name[LFS_NAME_MAX] = '\0'; + char f_name[512]; + memset(f_name, 'f', LFS_NAME_MAX); + f_name[LFS_NAME_MAX] = '\0'; + char g_name[512]; + memset(g_name, 'g', LFS_NAME_MAX); + g_name[LFS_NAME_MAX] = '\0'; + char h_name[512]; + memset(h_name, 'h', LFS_NAME_MAX); + h_name[LFS_NAME_MAX] = '\0'; + char i_name[512]; + memset(i_name, 'i', LFS_NAME_MAX); + i_name[LFS_NAME_MAX] = '\0'; + char j_name[512]; + memset(j_name, 'j', LFS_NAME_MAX); + j_name[LFS_NAME_MAX] = '\0'; + char k_name[512]; + memset(k_name, 'k', LFS_NAME_MAX); + k_name[LFS_NAME_MAX] = '\0'; + char l_name[512]; + memset(l_name, 'l', LFS_NAME_MAX); + l_name[LFS_NAME_MAX] = '\0'; + + // create names that aren't too long + lfsr_mkdir(&lfs, c_name) => 0; + char path[1024]; + if (DIR) { + sprintf(path, "%s/%s", c_name, a_name); + lfsr_mkdir(&lfs, path) => 0; + sprintf(path, "%s/%s", c_name, b_name); + lfsr_mkdir(&lfs, path) => 0; + sprintf(path, "%s/%s", c_name, c_name); + lfsr_mkdir(&lfs, path) => 0; + sprintf(path, "%s/%s", c_name, d_name); + lfsr_mkdir(&lfs, path) => 0; + sprintf(path, "%s/%s", c_name, e_name); + lfsr_mkdir(&lfs, path) => 0; + sprintf(path, "%s/%s", c_name, f_name); + lfsr_mkdir(&lfs, path) => 0; + } else { + lfsr_file_t file; + sprintf(path, "%s/%s", c_name, a_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + sprintf(path, "%s/%s", c_name, b_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + sprintf(path, "%s/%s", c_name, c_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + sprintf(path, "%s/%s", c_name, d_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + sprintf(path, "%s/%s", c_name, e_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + sprintf(path, "%s/%s", c_name, f_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + } + + // stat paths + struct lfs_info info; + sprintf(path, "%s/%s", c_name, a_name); + lfsr_stat(&lfs, path, &info) => 0; + assert(strcmp(info.name, a_name) == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + sprintf(path, "%s/%s", c_name, b_name); + lfsr_stat(&lfs, path, &info) => 0; + assert(strcmp(info.name, b_name) == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + sprintf(path, "%s/%s", c_name, c_name); + lfsr_stat(&lfs, path, &info) => 0; + assert(strcmp(info.name, c_name) == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + sprintf(path, "%s/%s", c_name, d_name); + lfsr_stat(&lfs, path, &info) => 0; + assert(strcmp(info.name, d_name) == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + sprintf(path, "%s/%s", c_name, e_name); + lfsr_stat(&lfs, path, &info) => 0; + assert(strcmp(info.name, e_name) == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + sprintf(path, "%s/%s", c_name, f_name); + lfsr_stat(&lfs, path, &info) => 0; + assert(strcmp(info.name, f_name) == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + // file open paths, only works on files! + if (DIR) { + lfsr_file_t file; + sprintf(path, "%s/%s", c_name, a_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_RDONLY) => LFS_ERR_ISDIR; + sprintf(path, "%s/%s", c_name, b_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_RDONLY) => LFS_ERR_ISDIR; + sprintf(path, "%s/%s", c_name, c_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_RDONLY) => LFS_ERR_ISDIR; + sprintf(path, "%s/%s", c_name, d_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_RDONLY) => LFS_ERR_ISDIR; + sprintf(path, "%s/%s", c_name, e_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_RDONLY) => LFS_ERR_ISDIR; + sprintf(path, "%s/%s", c_name, f_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_RDONLY) => LFS_ERR_ISDIR; + + sprintf(path, "%s/%s", c_name, a_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + sprintf(path, "%s/%s", c_name, b_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + sprintf(path, "%s/%s", c_name, c_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + sprintf(path, "%s/%s", c_name, d_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + sprintf(path, "%s/%s", c_name, e_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + sprintf(path, "%s/%s", c_name, f_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + sprintf(path, "%s/%s", c_name, a_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + sprintf(path, "%s/%s", c_name, b_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + sprintf(path, "%s/%s", c_name, c_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + sprintf(path, "%s/%s", c_name, d_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + sprintf(path, "%s/%s", c_name, e_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + sprintf(path, "%s/%s", c_name, f_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + } else { + lfsr_file_t file; + sprintf(path, "%s/%s", c_name, a_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + sprintf(path, "%s/%s", c_name, b_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + sprintf(path, "%s/%s", c_name, c_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + sprintf(path, "%s/%s", c_name, d_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + sprintf(path, "%s/%s", c_name, e_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + sprintf(path, "%s/%s", c_name, f_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + + sprintf(path, "%s/%s", c_name, a_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + sprintf(path, "%s/%s", c_name, b_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + sprintf(path, "%s/%s", c_name, c_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + sprintf(path, "%s/%s", c_name, d_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + sprintf(path, "%s/%s", c_name, e_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + sprintf(path, "%s/%s", c_name, f_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + + sprintf(path, "%s/%s", c_name, a_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + sprintf(path, "%s/%s", c_name, b_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + sprintf(path, "%s/%s", c_name, c_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + sprintf(path, "%s/%s", c_name, d_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + sprintf(path, "%s/%s", c_name, e_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + sprintf(path, "%s/%s", c_name, f_name); + lfsr_file_open(&lfs, &file, path, + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + } + + // dir open paths, only works on dirs! + if (DIR) { + lfsr_dir_t dir; + sprintf(path, "%s/%s", c_name, a_name); + lfsr_dir_open(&lfs, &dir, path) => 0; + lfsr_dir_close(&lfs, &dir) => 0; + sprintf(path, "%s/%s", c_name, b_name); + lfsr_dir_open(&lfs, &dir, path) => 0; + lfsr_dir_close(&lfs, &dir) => 0; + sprintf(path, "%s/%s", c_name, c_name); + lfsr_dir_open(&lfs, &dir, path) => 0; + lfsr_dir_close(&lfs, &dir) => 0; + sprintf(path, "%s/%s", c_name, d_name); + lfsr_dir_open(&lfs, &dir, path) => 0; + lfsr_dir_close(&lfs, &dir) => 0; + sprintf(path, "%s/%s", c_name, e_name); + lfsr_dir_open(&lfs, &dir, path) => 0; + lfsr_dir_close(&lfs, &dir) => 0; + sprintf(path, "%s/%s", c_name, f_name); + lfsr_dir_open(&lfs, &dir, path) => 0; + lfsr_dir_close(&lfs, &dir) => 0; + } else { + lfsr_dir_t dir; + sprintf(path, "%s/%s", c_name, a_name); + lfsr_dir_open(&lfs, &dir, path) => LFS_ERR_NOTDIR; + sprintf(path, "%s/%s", c_name, b_name); + lfsr_dir_open(&lfs, &dir, path) => LFS_ERR_NOTDIR; + sprintf(path, "%s/%s", c_name, c_name); + lfsr_dir_open(&lfs, &dir, path) => LFS_ERR_NOTDIR; + sprintf(path, "%s/%s", c_name, d_name); + lfsr_dir_open(&lfs, &dir, path) => LFS_ERR_NOTDIR; + sprintf(path, "%s/%s", c_name, e_name); + lfsr_dir_open(&lfs, &dir, path) => LFS_ERR_NOTDIR; + sprintf(path, "%s/%s", c_name, f_name); + lfsr_dir_open(&lfs, &dir, path) => LFS_ERR_NOTDIR; + } + + // rename paths + lfsr_mkdir(&lfs, e_name) => 0; + char path_[1024]; + sprintf(path, "%s/%s", c_name, a_name); + sprintf(path_, "%s/%s", e_name, g_name); + lfsr_rename(&lfs, path, path_) => 0; + sprintf(path, "%s/%s", c_name, b_name); + sprintf(path_, "%s/%s", e_name, h_name); + lfsr_rename(&lfs, path, path_) => 0; + sprintf(path, "%s/%s", c_name, c_name); + sprintf(path_, "%s/%s", e_name, i_name); + lfsr_rename(&lfs, path, path_) => 0; + sprintf(path, "%s/%s", c_name, d_name); + sprintf(path_, "%s/%s", e_name, j_name); + lfsr_rename(&lfs, path, path_) => 0; + sprintf(path, "%s/%s", c_name, e_name); + sprintf(path_, "%s/%s", e_name, k_name); + lfsr_rename(&lfs, path, path_) => 0; + sprintf(path, "%s/%s", c_name, f_name); + sprintf(path_, "%s/%s", e_name, l_name); + lfsr_rename(&lfs, path, path_) => 0; + + // stat paths + sprintf(path, "%s/%s", e_name, g_name); + lfsr_stat(&lfs, path, &info) => 0; + assert(strcmp(info.name, g_name) == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + sprintf(path, "%s/%s", e_name, h_name); + lfsr_stat(&lfs, path, &info) => 0; + assert(strcmp(info.name, h_name) == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + sprintf(path, "%s/%s", e_name, i_name); + lfsr_stat(&lfs, path, &info) => 0; + assert(strcmp(info.name, i_name) == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + sprintf(path, "%s/%s", e_name, j_name); + lfsr_stat(&lfs, path, &info) => 0; + assert(strcmp(info.name, j_name) == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + sprintf(path, "%s/%s", e_name, k_name); + lfsr_stat(&lfs, path, &info) => 0; + assert(strcmp(info.name, k_name) == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + sprintf(path, "%s/%s", e_name, l_name); + lfsr_stat(&lfs, path, &info) => 0; + assert(strcmp(info.name, l_name) == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + sprintf(path, "%s/%s", c_name, a_name); + lfsr_stat(&lfs, path, &info) => LFS_ERR_NOENT; + sprintf(path, "%s/%s", c_name, b_name); + lfsr_stat(&lfs, path, &info) => LFS_ERR_NOENT; + sprintf(path, "%s/%s", c_name, c_name); + lfsr_stat(&lfs, path, &info) => LFS_ERR_NOENT; + sprintf(path, "%s/%s", c_name, d_name); + lfsr_stat(&lfs, path, &info) => LFS_ERR_NOENT; + sprintf(path, "%s/%s", c_name, e_name); + lfsr_stat(&lfs, path, &info) => LFS_ERR_NOENT; + sprintf(path, "%s/%s", c_name, f_name); + lfsr_stat(&lfs, path, &info) => LFS_ERR_NOENT; + + // remove paths + sprintf(path, "%s/%s", e_name, g_name); + lfsr_remove(&lfs, path) => 0; + sprintf(path, "%s/%s", e_name, h_name); + lfsr_remove(&lfs, path) => 0; + sprintf(path, "%s/%s", e_name, i_name); + lfsr_remove(&lfs, path) => 0; + sprintf(path, "%s/%s", e_name, j_name); + lfsr_remove(&lfs, path) => 0; + sprintf(path, "%s/%s", e_name, k_name); + lfsr_remove(&lfs, path) => 0; + sprintf(path, "%s/%s", e_name, l_name); + lfsr_remove(&lfs, path) => 0; + + // stat paths + sprintf(path, "%s/%s", e_name, g_name); + lfsr_stat(&lfs, path, &info) => LFS_ERR_NOENT; + sprintf(path, "%s/%s", e_name, h_name); + lfsr_stat(&lfs, path, &info) => LFS_ERR_NOENT; + sprintf(path, "%s/%s", e_name, i_name); + lfsr_stat(&lfs, path, &info) => LFS_ERR_NOENT; + sprintf(path, "%s/%s", e_name, j_name); + lfsr_stat(&lfs, path, &info) => LFS_ERR_NOENT; + sprintf(path, "%s/%s", e_name, k_name); + lfsr_stat(&lfs, path, &info) => LFS_ERR_NOENT; + sprintf(path, "%s/%s", e_name, l_name); + lfsr_stat(&lfs, path, &info) => LFS_ERR_NOENT; + + lfsr_unmount(&lfs) => 0; +''' + +# a quick utf8 test, utf8 is easy to support +[cases.test_paths_utf8] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; + lfsr_mount(&lfs, LFS_F_RDWR, CFG) => 0; + + // create paths + lfsr_mkdir(&lfs, "coffee") => 0; + if (DIR) { + lfsr_mkdir(&lfs, "coffee/dripcoffee") => 0; + lfsr_mkdir(&lfs, "coffee/coldbrew") => 0; + lfsr_mkdir(&lfs, "coffee/türkkahvesi") => 0; + lfsr_mkdir(&lfs, "coffee/ꦏꦺꦴꦥꦶꦠꦸꦧꦿꦸꦏ꧀") => 0; + lfsr_mkdir(&lfs, "coffee/càphêđá") => 0; + lfsr_mkdir(&lfs, "coffee/โอเลี้ยง") => 0; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "coffee/dripcoffee", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/türkkahvesi", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/ꦏꦺꦴꦥꦶꦠꦸꦧꦿꦸꦏ꧀", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/càphêđá", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/โอเลี้ยง", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + } + + // stat paths + struct lfs_info info; + lfsr_stat(&lfs, "coffee/dripcoffee", &info) => 0; + assert(strcmp(info.name, "dripcoffee") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/coldbrew", &info) => 0; + assert(strcmp(info.name, "coldbrew") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/türkkahvesi", &info) => 0; + assert(strcmp(info.name, "türkkahvesi") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/ꦏꦺꦴꦥꦶꦠꦸꦧꦿꦸꦏ꧀", &info) => 0; + assert(strcmp(info.name, "ꦏꦺꦴꦥꦶꦠꦸꦧꦿꦸꦏ꧀") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/càphêđá", &info) => 0; + assert(strcmp(info.name, "càphêđá") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "coffee/โอเลี้ยง", &info) => 0; + assert(strcmp(info.name, "โอเลี้ยง") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + // file open paths, only works on files! + if (DIR) { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "coffee/dripcoffee", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/türkkahvesi", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/ꦏꦺꦴꦥꦶꦠꦸꦧꦿꦸꦏ꧀", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/càphêđá", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/โอเลี้ยง", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + + lfsr_file_open(&lfs, &file, "coffee/dripcoffee", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/türkkahvesi", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/ꦏꦺꦴꦥꦶꦠꦸꦧꦿꦸꦏ꧀", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/càphêđá", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "coffee/โอเลี้ยง", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfsr_file_open(&lfs, &file, "coffee/dripcoffee", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "coffee/türkkahvesi", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "coffee/ꦏꦺꦴꦥꦶꦠꦸꦧꦿꦸꦏ꧀", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "coffee/càphêđá", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "coffee/โอเลี้ยง", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "coffee/dripcoffee", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/türkkahvesi", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/ꦏꦺꦴꦥꦶꦠꦸꦧꦿꦸꦏ꧀", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/càphêđá", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/โอเลี้ยง", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + + lfsr_file_open(&lfs, &file, "coffee/dripcoffee", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/türkkahvesi", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/ꦏꦺꦴꦥꦶꦠꦸꦧꦿꦸꦏ꧀", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/càphêđá", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "coffee/โอเลี้ยง", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + + lfsr_file_open(&lfs, &file, "coffee/dripcoffee", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "coffee/coldbrew", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "coffee/türkkahvesi", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "coffee/ꦏꦺꦴꦥꦶꦠꦸꦧꦿꦸꦏ꧀", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "coffee/càphêđá", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "coffee/โอเลี้ยง", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + } + + // dir open paths, only works on dirs! + if (DIR) { + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "coffee/dripcoffee") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "coffee/coldbrew") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "coffee/türkkahvesi") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "coffee/ꦏꦺꦴꦥꦶꦠꦸꦧꦿꦸꦏ꧀") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "coffee/càphêđá") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "coffee/โอเลี้ยง") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + } else { + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "coffee/dripcoffee") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "coffee/coldbrew") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "coffee/türkkahvesi") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "coffee/ꦏꦺꦴꦥꦶꦠꦸꦧꦿꦸꦏ꧀") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "coffee/càphêđá") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "coffee/โอเลี้ยง") => LFS_ERR_NOTDIR; + } + + // rename paths + lfsr_mkdir(&lfs, "caffè") => 0; + lfsr_rename(&lfs, + "coffee/dripcoffee", + "caffè/espresso") => 0; + lfsr_rename(&lfs, + "coffee/coldbrew", + "caffè/americano") => 0; + lfsr_rename(&lfs, + "coffee/türkkahvesi", + "caffè/macchiato") => 0; + lfsr_rename(&lfs, + "coffee/ꦏꦺꦴꦥꦶꦠꦸꦧꦿꦸꦏ꧀", + "caffè/latte") => 0; + lfsr_rename(&lfs, + "coffee/càphêđá", + "caffè/cappuccino") => 0; + lfsr_rename(&lfs, + "coffee/โอเลี้ยง", + "caffè/mocha") => 0; + + // stat paths + lfsr_stat(&lfs, "caffè/espresso", &info) => 0; + assert(strcmp(info.name, "espresso") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "caffè/americano", &info) => 0; + assert(strcmp(info.name, "americano") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "caffè/macchiato", &info) => 0; + assert(strcmp(info.name, "macchiato") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "caffè/latte", &info) => 0; + assert(strcmp(info.name, "latte") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "caffè/cappuccino", &info) => 0; + assert(strcmp(info.name, "cappuccino") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "caffè/mocha", &info) => 0; + assert(strcmp(info.name, "mocha") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfsr_stat(&lfs, "coffee/dripcoffee", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/coldbrew", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/türkkahvesi", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/ꦏꦺꦴꦥꦶꦠꦸꦧꦿꦸꦏ꧀", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/càphêđá", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "coffee/โอเลี้ยง", &info) => LFS_ERR_NOENT; + + // remove paths + lfsr_remove(&lfs, "caffè/espresso") => 0; + lfsr_remove(&lfs, "caffè/americano") => 0; + lfsr_remove(&lfs, "caffè/macchiato") => 0; + lfsr_remove(&lfs, "caffè/latte") => 0; + lfsr_remove(&lfs, "caffè/cappuccino") => 0; + lfsr_remove(&lfs, "caffè/mocha") => 0; + + // stat paths + lfsr_stat(&lfs, "caffè/espresso", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "caffè/americano", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "caffè/macchiato", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "caffè/latte", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "caffè/cappuccino", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "caffè/mocha", &info) => LFS_ERR_NOENT; + + lfsr_unmount(&lfs) => 0; +''' + +# more utf8 tests +[cases.test_paths_utf8_ipa] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; + lfsr_mount(&lfs, LFS_F_RDWR, CFG) => 0; + + // create paths + lfsr_mkdir(&lfs, "ˈkɔ.fi") => 0; + if (DIR) { + lfsr_mkdir(&lfs, "ˈkɔ.fi/dɹɪpˈkɔ.fi") => 0; + lfsr_mkdir(&lfs, "ˈkɔ.fi/koʊldbɹuː") => 0; + lfsr_mkdir(&lfs, "ˈkɔ.fi/tyɾckɑhvɛˈsi") => 0; + lfsr_mkdir(&lfs, "ˈkɔ.fi/ˈko.piˈt̪up̚.rʊk̚") => 0; + lfsr_mkdir(&lfs, "ˈkɔ.fi/kaː˨˩fe˧˧ɗaː˧˥") => 0; + lfsr_mkdir(&lfs, "ˈkɔ.fi/ʔoː˧.lia̯ŋ˦˥") => 0; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/dɹɪpˈkɔ.fi", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/koʊldbɹuː", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/tyɾckɑhvɛˈsi", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/ˈko.piˈt̪up̚.rʊk̚", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/kaː˨˩fe˧˧ɗaː˧˥", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/ʔoː˧.lia̯ŋ˦˥", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + } + + // stat paths + struct lfs_info info; + lfsr_stat(&lfs, "ˈkɔ.fi/dɹɪpˈkɔ.fi", &info) => 0; + assert(strcmp(info.name, "dɹɪpˈkɔ.fi") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "ˈkɔ.fi/koʊldbɹuː", &info) => 0; + assert(strcmp(info.name, "koʊldbɹuː") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "ˈkɔ.fi/tyɾckɑhvɛˈsi", &info) => 0; + assert(strcmp(info.name, "tyɾckɑhvɛˈsi") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "ˈkɔ.fi/ˈko.piˈt̪up̚.rʊk̚", &info) => 0; + assert(strcmp(info.name, "ˈko.piˈt̪up̚.rʊk̚") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "ˈkɔ.fi/kaː˨˩fe˧˧ɗaː˧˥", &info) => 0; + assert(strcmp(info.name, "kaː˨˩fe˧˧ɗaː˧˥") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "ˈkɔ.fi/ʔoː˧.lia̯ŋ˦˥", &info) => 0; + assert(strcmp(info.name, "ʔoː˧.lia̯ŋ˦˥") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + // file open paths, only works on files! + if (DIR) { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/dɹɪpˈkɔ.fi", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/koʊldbɹuː", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/tyɾckɑhvɛˈsi", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/ˈko.piˈt̪up̚.rʊk̚", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/kaː˨˩fe˧˧ɗaː˧˥", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/ʔoː˧.lia̯ŋ˦˥", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/dɹɪpˈkɔ.fi", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/koʊldbɹuː", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/tyɾckɑhvɛˈsi", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/ˈko.piˈt̪up̚.rʊk̚", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/kaː˨˩fe˧˧ɗaː˧˥", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/ʔoː˧.lia̯ŋ˦˥", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/dɹɪpˈkɔ.fi", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/koʊldbɹuː", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/tyɾckɑhvɛˈsi", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/ˈko.piˈt̪up̚.rʊk̚", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/kaː˨˩fe˧˧ɗaː˧˥", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/ʔoː˧.lia̯ŋ˦˥", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/dɹɪpˈkɔ.fi", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/koʊldbɹuː", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/tyɾckɑhvɛˈsi", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/ˈko.piˈt̪up̚.rʊk̚", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/kaː˨˩fe˧˧ɗaː˧˥", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/ʔoː˧.lia̯ŋ˦˥", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/dɹɪpˈkɔ.fi", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/koʊldbɹuː", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/tyɾckɑhvɛˈsi", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/ˈko.piˈt̪up̚.rʊk̚", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/kaː˨˩fe˧˧ɗaː˧˥", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/ʔoː˧.lia̯ŋ˦˥", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/dɹɪpˈkɔ.fi", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/koʊldbɹuː", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/tyɾckɑhvɛˈsi", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/ˈko.piˈt̪up̚.rʊk̚", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/kaː˨˩fe˧˧ɗaː˧˥", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "ˈkɔ.fi/ʔoː˧.lia̯ŋ˦˥", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + } + + // dir open paths, only works on dirs! + if (DIR) { + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "ˈkɔ.fi/dɹɪpˈkɔ.fi") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "ˈkɔ.fi/koʊldbɹuː") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "ˈkɔ.fi/tyɾckɑhvɛˈsi") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "ˈkɔ.fi/ˈko.piˈt̪up̚.rʊk̚") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "ˈkɔ.fi/kaː˨˩fe˧˧ɗaː˧˥") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "ˈkɔ.fi/ʔoː˧.lia̯ŋ˦˥") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + } else { + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "ˈkɔ.fi/dɹɪpˈkɔ.fi") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "ˈkɔ.fi/koʊldbɹuː") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "ˈkɔ.fi/tyɾckɑhvɛˈsi") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "ˈkɔ.fi/ˈko.piˈt̪up̚.rʊk̚") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "ˈkɔ.fi/kaː˨˩fe˧˧ɗaː˧˥") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "ˈkɔ.fi/ʔoː˧.lia̯ŋ˦˥") => LFS_ERR_NOTDIR; + } + + // rename paths + lfsr_mkdir(&lfs, "kafˈfɛ") => 0; + lfsr_rename(&lfs, + "ˈkɔ.fi/dɹɪpˈkɔ.fi", + "kafˈfɛ/eˈsprɛsso") => 0; + lfsr_rename(&lfs, + "ˈkɔ.fi/koʊldbɹuː", + "kafˈfɛ/ameriˈkano") => 0; + lfsr_rename(&lfs, + "ˈkɔ.fi/tyɾckɑhvɛˈsi", + "kafˈfɛ/makˈkjato") => 0; + lfsr_rename(&lfs, + "ˈkɔ.fi/ˈko.piˈt̪up̚.rʊk̚", + "kafˈfɛ/ˈlat.te") => 0; + lfsr_rename(&lfs, + "ˈkɔ.fi/kaː˨˩fe˧˧ɗaː˧˥", + "kafˈfɛ/kapputˈt͡ʃino") => 0; + lfsr_rename(&lfs, + "ˈkɔ.fi/ʔoː˧.lia̯ŋ˦˥", + "kafˈfɛ/ˈmoʊkə") => 0; + + // stat paths + lfsr_stat(&lfs, "kafˈfɛ/eˈsprɛsso", &info) => 0; + assert(strcmp(info.name, "eˈsprɛsso") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "kafˈfɛ/ameriˈkano", &info) => 0; + assert(strcmp(info.name, "ameriˈkano") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "kafˈfɛ/makˈkjato", &info) => 0; + assert(strcmp(info.name, "makˈkjato") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "kafˈfɛ/ˈlat.te", &info) => 0; + assert(strcmp(info.name, "ˈlat.te") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "kafˈfɛ/kapputˈt͡ʃino", &info) => 0; + assert(strcmp(info.name, "kapputˈt͡ʃino") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "kafˈfɛ/ˈmoʊkə", &info) => 0; + assert(strcmp(info.name, "ˈmoʊkə") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfsr_stat(&lfs, "ˈkɔ.fi/dɹɪpˈkɔ.fi", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "ˈkɔ.fi/koʊldbɹuː", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "ˈkɔ.fi/tyɾckɑhvɛˈsi", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "ˈkɔ.fi/ˈko.piˈt̪up̚.rʊk̚", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "ˈkɔ.fi/kaː˨˩fe˧˧ɗaː˧˥", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "ˈkɔ.fi/ʔoː˧.lia̯ŋ˦˥", &info) => LFS_ERR_NOENT; + + // remove paths + lfsr_remove(&lfs, "kafˈfɛ/eˈsprɛsso") => 0; + lfsr_remove(&lfs, "kafˈfɛ/ameriˈkano") => 0; + lfsr_remove(&lfs, "kafˈfɛ/makˈkjato") => 0; + lfsr_remove(&lfs, "kafˈfɛ/ˈlat.te") => 0; + lfsr_remove(&lfs, "kafˈfɛ/kapputˈt͡ʃino") => 0; + lfsr_remove(&lfs, "kafˈfɛ/ˈmoʊkə") => 0; + + // stat paths + lfsr_stat(&lfs, "kafˈfɛ/eˈsprɛsso", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "kafˈfɛ/ameriˈkano", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "kafˈfɛ/makˈkjato", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "kafˈfɛ/ˈlat.te", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "kafˈfɛ/kapputˈt͡ʃino", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "kafˈfɛ/ˈmoʊkə", &info) => LFS_ERR_NOENT; + + lfsr_unmount(&lfs) => 0; +''' + +# test spaces have no problems +[cases.test_paths_spaces] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; + lfsr_mount(&lfs, LFS_F_RDWR, CFG) => 0; + + // create paths + lfsr_mkdir(&lfs, "c o f f e e") => 0; + if (DIR) { + lfsr_mkdir(&lfs, "c o f f e e/d r i p") => 0; + lfsr_mkdir(&lfs, "c o f f e e/c o l d b r e w") => 0; + lfsr_mkdir(&lfs, "c o f f e e/t u r k i s h") => 0; + lfsr_mkdir(&lfs, "c o f f e e/t u b r u k") => 0; + lfsr_mkdir(&lfs, "c o f f e e/v i e t n a m e s e") => 0; + lfsr_mkdir(&lfs, "c o f f e e/t h a i") => 0; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "c o f f e e/d r i p", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "c o f f e e/c o l d b r e w", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "c o f f e e/t u r k i s h", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "c o f f e e/t u b r u k", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "c o f f e e/v i e t n a m e s e", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "c o f f e e/t h a i", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + } + + // stat paths + struct lfs_info info; + lfsr_stat(&lfs, "c o f f e e/d r i p", &info) => 0; + assert(strcmp(info.name, "d r i p") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "c o f f e e/c o l d b r e w", &info) => 0; + assert(strcmp(info.name, "c o l d b r e w") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "c o f f e e/t u r k i s h", &info) => 0; + assert(strcmp(info.name, "t u r k i s h") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "c o f f e e/t u b r u k", &info) => 0; + assert(strcmp(info.name, "t u b r u k") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "c o f f e e/v i e t n a m e s e", &info) => 0; + assert(strcmp(info.name, "v i e t n a m e s e") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "c o f f e e/t h a i", &info) => 0; + assert(strcmp(info.name, "t h a i") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + // file open paths, only works on files! + if (DIR) { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "c o f f e e/d r i p", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "c o f f e e/c o l d b r e w", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "c o f f e e/t u r k i s h", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "c o f f e e/t u b r u k", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "c o f f e e/v i e t n a m e s e", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "c o f f e e/t h a i", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + + lfsr_file_open(&lfs, &file, "c o f f e e/d r i p", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "c o f f e e/c o l d b r e w", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "c o f f e e/t u r k i s h", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "c o f f e e/t u b r u k", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "c o f f e e/v i e t n a m e s e", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "c o f f e e/t h a i", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfsr_file_open(&lfs, &file, "c o f f e e/d r i p", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "c o f f e e/c o l d b r e w", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "c o f f e e/t u r k i s h", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "c o f f e e/t u b r u k", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "c o f f e e/v i e t n a m e s e", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "c o f f e e/t h a i", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "c o f f e e/d r i p", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "c o f f e e/c o l d b r e w", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "c o f f e e/t u r k i s h", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "c o f f e e/t u b r u k", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "c o f f e e/v i e t n a m e s e", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "c o f f e e/t h a i", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + + lfsr_file_open(&lfs, &file, "c o f f e e/d r i p", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "c o f f e e/c o l d b r e w", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "c o f f e e/t u r k i s h", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "c o f f e e/t u b r u k", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "c o f f e e/v i e t n a m e s e", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "c o f f e e/t h a i", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + + lfsr_file_open(&lfs, &file, "c o f f e e/d r i p", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "c o f f e e/c o l d b r e w", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "c o f f e e/t u r k i s h", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "c o f f e e/t u b r u k", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "c o f f e e/v i e t n a m e s e", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "c o f f e e/t h a i", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + } + + // dir open paths, only works on dirs! + if (DIR) { + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "c o f f e e/d r i p") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "c o f f e e/c o l d b r e w") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "c o f f e e/t u r k i s h") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "c o f f e e/t u b r u k") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "c o f f e e/v i e t n a m e s e") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "c o f f e e/t h a i") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + } else { + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "c o f f e e/d r i p") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "c o f f e e/c o l d b r e w") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "c o f f e e/t u r k i s h") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "c o f f e e/t u b r u k") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "c o f f e e/v i e t n a m e s e") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "c o f f e e/t h a i") => LFS_ERR_NOTDIR; + } + + // rename paths + lfsr_mkdir(&lfs, "e s p r e s s o") => 0; + lfsr_rename(&lfs, + "c o f f e e/d r i p", + "e s p r e s s o/e s p r e s s o") => 0; + lfsr_rename(&lfs, + "c o f f e e/c o l d b r e w", + "e s p r e s s o/a m e r i c a n o") => 0; + lfsr_rename(&lfs, + "c o f f e e/t u r k i s h", + "e s p r e s s o/m a c c h i a t o") => 0; + lfsr_rename(&lfs, + "c o f f e e/t u b r u k", + "e s p r e s s o/l a t t e") => 0; + lfsr_rename(&lfs, + "c o f f e e/v i e t n a m e s e", + "e s p r e s s o/c a p p u c c i n o") => 0; + lfsr_rename(&lfs, + "c o f f e e/t h a i", + "e s p r e s s o/m o c h a") => 0; + + // stat paths + lfsr_stat(&lfs, "e s p r e s s o/e s p r e s s o", &info) => 0; + assert(strcmp(info.name, "e s p r e s s o") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "e s p r e s s o/a m e r i c a n o", &info) => 0; + assert(strcmp(info.name, "a m e r i c a n o") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "e s p r e s s o/m a c c h i a t o", &info) => 0; + assert(strcmp(info.name, "m a c c h i a t o") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "e s p r e s s o/l a t t e", &info) => 0; + assert(strcmp(info.name, "l a t t e") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "e s p r e s s o/c a p p u c c i n o", &info) => 0; + assert(strcmp(info.name, "c a p p u c c i n o") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "e s p r e s s o/m o c h a", &info) => 0; + assert(strcmp(info.name, "m o c h a") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfsr_stat(&lfs, "c o f f e e/d r i p", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "c o f f e e/c o l d b r e w", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "c o f f e e/t u r k i s h", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "c o f f e e/t u b r u k", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "c o f f e e/v i e t n a m e s e", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "c o f f e e/t h a i", &info) => LFS_ERR_NOENT; + + // remove paths + lfsr_remove(&lfs, "e s p r e s s o/e s p r e s s o") => 0; + lfsr_remove(&lfs, "e s p r e s s o/a m e r i c a n o") => 0; + lfsr_remove(&lfs, "e s p r e s s o/m a c c h i a t o") => 0; + lfsr_remove(&lfs, "e s p r e s s o/l a t t e") => 0; + lfsr_remove(&lfs, "e s p r e s s o/c a p p u c c i n o") => 0; + lfsr_remove(&lfs, "e s p r e s s o/m o c h a") => 0; + + // stat paths + lfsr_stat(&lfs, "e s p r e s s o/e s p r e s s o", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "e s p r e s s o/a m e r i c a n o", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "e s p r e s s o/m a c c h i a t o", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "e s p r e s s o/l a t t e", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "e s p r e s s o/c a p p u c c i n o", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "e s p r e s s o/m o c h a", &info) => LFS_ERR_NOENT; + + lfsr_unmount(&lfs) => 0; +''' + +# test with only spaces +# +# please don't do this +[cases.test_paths_oopsallspaces] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; + lfsr_mount(&lfs, LFS_F_RDWR, CFG) => 0; + + // create paths + lfsr_mkdir(&lfs, " ") => 0; + if (DIR) { + lfsr_mkdir(&lfs, " / ") => 0; + lfsr_mkdir(&lfs, " / ") => 0; + lfsr_mkdir(&lfs, " / ") => 0; + lfsr_mkdir(&lfs, " / ") => 0; + lfsr_mkdir(&lfs, " / ") => 0; + lfsr_mkdir(&lfs, " / ") => 0; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + } + + // stat paths + struct lfs_info info; + lfsr_stat(&lfs, " / ", &info) => 0; + assert(strcmp(info.name, " ") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, " / ", &info) => 0; + assert(strcmp(info.name, " ") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, " / ", &info) => 0; + assert(strcmp(info.name, " ") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, " / ", &info) => 0; + assert(strcmp(info.name, " ") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, " / ", &info) => 0; + assert(strcmp(info.name, " ") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, " / ", &info) => 0; + assert(strcmp(info.name, " ") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + // file open paths, only works on files! + if (DIR) { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, " / ", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, " / ", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, " / ", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, " / ", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, " / ", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, " / ", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + + lfsr_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfsr_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, " / ", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, " / ", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, " / ", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, " / ", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, " / ", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, " / ", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + + lfsr_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + + lfsr_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, " / ", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + } + + // dir open paths, only works on dirs! + if (DIR) { + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, " / ") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, " / ") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, " / ") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, " / ") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, " / ") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, " / ") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + } else { + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, " / ") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, " / ") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, " / ") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, " / ") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, " / ") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, " / ") => LFS_ERR_NOTDIR; + } + + // rename paths + lfsr_mkdir(&lfs, " ") => 0; + lfsr_rename(&lfs, + " / ", + " / ") => 0; + lfsr_rename(&lfs, + " / ", + " / ") => 0; + lfsr_rename(&lfs, + " / ", + " / ") => 0; + lfsr_rename(&lfs, + " / ", + " / ") => 0; + lfsr_rename(&lfs, + " / ", + " / ") => 0; + lfsr_rename(&lfs, + " / ", + " / ") => 0; + + // stat paths + lfsr_stat(&lfs, " / ", &info) => 0; + assert(strcmp(info.name, " ") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, " / ", &info) => 0; + assert(strcmp(info.name, " ") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, " / ", &info) => 0; + assert(strcmp(info.name, " ") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, " / ", &info) => 0; + assert(strcmp(info.name, " ") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, " / ", &info) => 0; + assert(strcmp(info.name, " ") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, " / ", &info) => 0; + assert(strcmp(info.name, " ") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfsr_stat(&lfs, " / ", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, " / ", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, " / ", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, " / ", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, " / ", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, " / ", &info) => LFS_ERR_NOENT; + + // remove paths + lfsr_remove(&lfs, " / ") => 0; + lfsr_remove(&lfs, " / ") => 0; + lfsr_remove(&lfs, " / ") => 0; + lfsr_remove(&lfs, " / ") => 0; + lfsr_remove(&lfs, " / ") => 0; + lfsr_remove(&lfs, " / ") => 0; + + // stat paths + lfsr_stat(&lfs, " / ", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, " / ", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, " / ", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, " / ", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, " / ", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, " / ", &info) => LFS_ERR_NOENT; + + lfsr_unmount(&lfs) => 0; +''' + +# test with only ascii control characters +# +# littlefs only cares about "./" and NULL +[cases.test_paths_nonprintable] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; + lfsr_mount(&lfs, LFS_F_RDWR, CFG) => 0; + + // create paths + lfsr_mkdir(&lfs, "\x0c") => 0; + if (DIR) { + lfsr_mkdir(&lfs, "\x0c/\x01") => 0; + lfsr_mkdir(&lfs, "\x0c/\x02") => 0; + lfsr_mkdir(&lfs, "\x0c/\x03") => 0; + lfsr_mkdir(&lfs, "\x0c/\x04") => 0; + lfsr_mkdir(&lfs, "\x0c/\x05") => 0; + lfsr_mkdir(&lfs, "\x0c/\x06") => 0; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "\x0c/\x01", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\x0c/\x02", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\x0c/\x03", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\x0c/\x04", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\x0c/\x05", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\x0c/\x06", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + } + + // stat paths + struct lfs_info info; + lfsr_stat(&lfs, "\x0c/\x01", &info) => 0; + assert(strcmp(info.name, "\x01") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "\x0c/\x02", &info) => 0; + assert(strcmp(info.name, "\x02") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "\x0c/\x03", &info) => 0; + assert(strcmp(info.name, "\x03") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "\x0c/\x04", &info) => 0; + assert(strcmp(info.name, "\x04") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "\x0c/\x05", &info) => 0; + assert(strcmp(info.name, "\x05") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "\x0c/\x06", &info) => 0; + assert(strcmp(info.name, "\x06") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + // file open paths, only works on files! + if (DIR) { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "\x0c/\x01", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "\x0c/\x02", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "\x0c/\x03", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "\x0c/\x04", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "\x0c/\x05", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "\x0c/\x06", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + + lfsr_file_open(&lfs, &file, "\x0c/\x01", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "\x0c/\x02", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "\x0c/\x03", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "\x0c/\x04", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "\x0c/\x05", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "\x0c/\x06", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfsr_file_open(&lfs, &file, "\x0c/\x01", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "\x0c/\x02", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "\x0c/\x03", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "\x0c/\x04", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "\x0c/\x05", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "\x0c/\x06", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "\x0c/\x01", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\x0c/\x02", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\x0c/\x03", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\x0c/\x04", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\x0c/\x05", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\x0c/\x06", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + + lfsr_file_open(&lfs, &file, "\x0c/\x01", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\x0c/\x02", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\x0c/\x03", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\x0c/\x04", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\x0c/\x05", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\x0c/\x06", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + + lfsr_file_open(&lfs, &file, "\x0c/\x01", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "\x0c/\x02", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "\x0c/\x03", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "\x0c/\x04", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "\x0c/\x05", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "\x0c/\x06", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + } + + // dir open paths, only works on dirs! + if (DIR) { + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "\x0c/\x01") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "\x0c/\x02") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "\x0c/\x03") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "\x0c/\x04") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "\x0c/\x05") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "\x0c/\x06") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + } else { + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "\x0c/\x01") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "\x0c/\x02") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "\x0c/\x03") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "\x0c/\x04") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "\x0c/\x05") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "\x0c/\x06") => LFS_ERR_NOTDIR; + } + + // rename paths + lfsr_mkdir(&lfs, "\x0e") => 0; + lfsr_rename(&lfs, + "\x0c/\x01", + "\x0e/\x1a") => 0; + lfsr_rename(&lfs, + "\x0c/\x02", + "\x0e/\x1b") => 0; + lfsr_rename(&lfs, + "\x0c/\x03", + "\x0e/\x1c") => 0; + lfsr_rename(&lfs, + "\x0c/\x04", + "\x0e/\x1d") => 0; + lfsr_rename(&lfs, + "\x0c/\x05", + "\x0e/\x1e") => 0; + lfsr_rename(&lfs, + "\x0c/\x06", + "\x0e/\x1f") => 0; + + // stat paths + lfsr_stat(&lfs, "\x0e/\x1a", &info) => 0; + assert(strcmp(info.name, "\x1a") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "\x0e/\x1b", &info) => 0; + assert(strcmp(info.name, "\x1b") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "\x0e/\x1c", &info) => 0; + assert(strcmp(info.name, "\x1c") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "\x0e/\x1d", &info) => 0; + assert(strcmp(info.name, "\x1d") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "\x0e/\x1e", &info) => 0; + assert(strcmp(info.name, "\x1e") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "\x0e/\x1f", &info) => 0; + assert(strcmp(info.name, "\x1f") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfsr_stat(&lfs, "\x0c/\x01", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "\x0c/\x02", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "\x0c/\x03", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "\x0c/\x04", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "\x0c/\x05", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "\x0c/\x06", &info) => LFS_ERR_NOENT; + + // remove paths + lfsr_remove(&lfs, "\x0e/\x1a") => 0; + lfsr_remove(&lfs, "\x0e/\x1b") => 0; + lfsr_remove(&lfs, "\x0e/\x1c") => 0; + lfsr_remove(&lfs, "\x0e/\x1d") => 0; + lfsr_remove(&lfs, "\x0e/\x1e") => 0; + lfsr_remove(&lfs, "\x0e/\x1f") => 0; + + // stat paths + lfsr_stat(&lfs, "\x0e/\x1a", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "\x0e/\x1b", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "\x0e/\x1c", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "\x0e/\x1d", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "\x0e/\x1e", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "\x0e/\x1f", &info) => LFS_ERR_NOENT; + + lfsr_unmount(&lfs) => 0; +''' + +# test with only ascii DELs +# +# I don't know why you'd do this +[cases.test_paths_oopsalldels] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; + lfsr_mount(&lfs, LFS_F_RDWR, CFG) => 0; + + // create paths + lfsr_mkdir(&lfs, "\x7f") => 0; + if (DIR) { + lfsr_mkdir(&lfs, "\x7f/\x7f") => 0; + lfsr_mkdir(&lfs, "\x7f/\x7f\x7f") => 0; + lfsr_mkdir(&lfs, "\x7f/\x7f\x7f\x7f") => 0; + lfsr_mkdir(&lfs, "\x7f/\x7f\x7f\x7f\x7f") => 0; + lfsr_mkdir(&lfs, "\x7f/\x7f\x7f\x7f\x7f\x7f") => 0; + lfsr_mkdir(&lfs, "\x7f/\x7f\x7f\x7f\x7f\x7f\x7f") => 0; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "\x7f/\x7f", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\x7f/\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + } + + // stat paths + struct lfs_info info; + lfsr_stat(&lfs, "\x7f/\x7f", &info) => 0; + assert(strcmp(info.name, "\x7f") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "\x7f/\x7f\x7f", &info) => 0; + assert(strcmp(info.name, "\x7f\x7f") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "\x7f/\x7f\x7f\x7f", &info) => 0; + assert(strcmp(info.name, "\x7f\x7f\x7f") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "\x7f/\x7f\x7f\x7f\x7f", &info) => 0; + assert(strcmp(info.name, "\x7f\x7f\x7f\x7f") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "\x7f/\x7f\x7f\x7f\x7f\x7f", &info) => 0; + assert(strcmp(info.name, "\x7f\x7f\x7f\x7f\x7f") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "\x7f/\x7f\x7f\x7f\x7f\x7f\x7f", &info) => 0; + assert(strcmp(info.name, "\x7f\x7f\x7f\x7f\x7f\x7f") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + // file open paths, only works on files! + if (DIR) { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "\x7f/\x7f", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "\x7f/\x7f\x7f", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f\x7f", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f\x7f\x7f", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + + lfsr_file_open(&lfs, &file, "\x7f/\x7f", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "\x7f/\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfsr_file_open(&lfs, &file, "\x7f/\x7f", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "\x7f/\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "\x7f/\x7f", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\x7f/\x7f\x7f", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f\x7f", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f\x7f\x7f", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + + lfsr_file_open(&lfs, &file, "\x7f/\x7f", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\x7f/\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + + lfsr_file_open(&lfs, &file, "\x7f/\x7f", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "\x7f/\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "\x7f/\x7f\x7f\x7f\x7f\x7f\x7f", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + } + + // dir open paths, only works on dirs! + if (DIR) { + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "\x7f/\x7f") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "\x7f/\x7f\x7f") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "\x7f/\x7f\x7f\x7f") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "\x7f/\x7f\x7f\x7f\x7f") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "\x7f/\x7f\x7f\x7f\x7f\x7f") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "\x7f/\x7f\x7f\x7f\x7f\x7f\x7f") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + } else { + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "\x7f/\x7f") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "\x7f/\x7f\x7f") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "\x7f/\x7f\x7f\x7f") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "\x7f/\x7f\x7f\x7f\x7f") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "\x7f/\x7f\x7f\x7f\x7f\x7f") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "\x7f/\x7f\x7f\x7f\x7f\x7f\x7f") => LFS_ERR_NOTDIR; + } + + // rename paths + lfsr_mkdir(&lfs, "\x7f\x7f") => 0; + lfsr_rename(&lfs, + "\x7f/\x7f", + "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f") => 0; + lfsr_rename(&lfs, + "\x7f/\x7f\x7f", + "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f\x7f") => 0; + lfsr_rename(&lfs, + "\x7f/\x7f\x7f\x7f", + "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f") => 0; + lfsr_rename(&lfs, + "\x7f/\x7f\x7f\x7f\x7f", + "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f") => 0; + lfsr_rename(&lfs, + "\x7f/\x7f\x7f\x7f\x7f\x7f", + "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f") => 0; + lfsr_rename(&lfs, + "\x7f/\x7f\x7f\x7f\x7f\x7f\x7f", + "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f") => 0; + + // stat paths + lfsr_stat(&lfs, "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f", &info) => 0; + assert(strcmp(info.name, "\x7f\x7f\x7f\x7f\x7f\x7f") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f\x7f", &info) => 0; + assert(strcmp(info.name, "\x7f\x7f\x7f\x7f\x7f\x7f\x7f") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f", &info) => 0; + assert(strcmp(info.name, "\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f", &info) => 0; + assert(strcmp(info.name, "\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f", &info) => 0; + assert(strcmp(info.name, "\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f", &info) => 0; + assert(strcmp(info.name, "\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfsr_stat(&lfs, "\x7f/\x7f", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "\x7f/\x7f\x7f", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "\x7f/\x7f\x7f\x7f", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "\x7f/\x7f\x7f\x7f\x7f", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "\x7f/\x7f\x7f\x7f\x7f\x7f", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "\x7f/\x7f\x7f\x7f\x7f\x7f\x7f", &info) => LFS_ERR_NOENT; + + // remove paths + lfsr_remove(&lfs, "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f") => 0; + lfsr_remove(&lfs, "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f\x7f") => 0; + lfsr_remove(&lfs, "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f") => 0; + lfsr_remove(&lfs, "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f") => 0; + lfsr_remove(&lfs, "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f") => 0; + lfsr_remove(&lfs, "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f") => 0; + + // stat paths + lfsr_stat(&lfs, "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f\x7f", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "\x7f\x7f/\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f", &info) => LFS_ERR_NOENT; + + lfsr_unmount(&lfs) => 0; +''' + +# test with invalid utf8 sequences +# +# Don't do this! These filenames are not utf8 and will probably break +# external tools. +# +[cases.test_paths_nonutf8] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; + lfsr_mount(&lfs, LFS_F_RDWR, CFG) => 0; + + // create paths + lfsr_mkdir(&lfs, "\xc0") => 0; + if (DIR) { + lfsr_mkdir(&lfs, "\xc0/\xa0") => 0; + lfsr_mkdir(&lfs, "\xc0/\xb0") => 0; + lfsr_mkdir(&lfs, "\xc0/\xc0") => 0; + lfsr_mkdir(&lfs, "\xc0/\xd0") => 0; + lfsr_mkdir(&lfs, "\xc0/\xe0") => 0; + lfsr_mkdir(&lfs, "\xc0/\xf0") => 0; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "\xc0/\xa0", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\xc0/\xb0", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\xc0/\xc0", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\xc0/\xd0", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\xc0/\xe0", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\xc0/\xf0", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + } + + // stat paths + struct lfs_info info; + lfsr_stat(&lfs, "\xc0/\xa0", &info) => 0; + assert(strcmp(info.name, "\xa0") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "\xc0/\xb0", &info) => 0; + assert(strcmp(info.name, "\xb0") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "\xc0/\xc0", &info) => 0; + assert(strcmp(info.name, "\xc0") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "\xc0/\xd0", &info) => 0; + assert(strcmp(info.name, "\xd0") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "\xc0/\xe0", &info) => 0; + assert(strcmp(info.name, "\xe0") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "\xc0/\xf0", &info) => 0; + assert(strcmp(info.name, "\xf0") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + // file open paths, only works on files! + if (DIR) { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "\xc0/\xa0", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "\xc0/\xb0", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "\xc0/\xc0", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "\xc0/\xd0", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "\xc0/\xe0", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "\xc0/\xf0", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + + lfsr_file_open(&lfs, &file, "\xc0/\xa0", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "\xc0/\xb0", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "\xc0/\xc0", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "\xc0/\xd0", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "\xc0/\xe0", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "\xc0/\xf0", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfsr_file_open(&lfs, &file, "\xc0/\xa0", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "\xc0/\xb0", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "\xc0/\xc0", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "\xc0/\xd0", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "\xc0/\xe0", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "\xc0/\xf0", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "\xc0/\xa0", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\xc0/\xb0", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\xc0/\xc0", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\xc0/\xd0", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\xc0/\xe0", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\xc0/\xf0", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + + lfsr_file_open(&lfs, &file, "\xc0/\xa0", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\xc0/\xb0", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\xc0/\xc0", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\xc0/\xd0", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\xc0/\xe0", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\xc0/\xf0", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + + lfsr_file_open(&lfs, &file, "\xc0/\xa0", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "\xc0/\xb0", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "\xc0/\xc0", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "\xc0/\xd0", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "\xc0/\xe0", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "\xc0/\xf0", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + } + + // dir open paths, only works on dirs! + if (DIR) { + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "\xc0/\xa0") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "\xc0/\xb0") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "\xc0/\xc0") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "\xc0/\xd0") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "\xc0/\xe0") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "\xc0/\xf0") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + } else { + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "\xc0/\xa0") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "\xc0/\xb0") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "\xc0/\xc0") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "\xc0/\xd0") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "\xc0/\xe0") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "\xc0/\xf0") => LFS_ERR_NOTDIR; + } + + // rename paths + lfsr_mkdir(&lfs, "\xe0") => 0; + lfsr_rename(&lfs, + "\xc0/\xa0", + "\xe0/\xaf") => 0; + lfsr_rename(&lfs, + "\xc0/\xb0", + "\xe0/\xbf") => 0; + lfsr_rename(&lfs, + "\xc0/\xc0", + "\xe0/\xcf") => 0; + lfsr_rename(&lfs, + "\xc0/\xd0", + "\xe0/\xdf") => 0; + lfsr_rename(&lfs, + "\xc0/\xe0", + "\xe0/\xef") => 0; + lfsr_rename(&lfs, + "\xc0/\xf0", + "\xe0/\xff") => 0; + + // stat paths + lfsr_stat(&lfs, "\xe0/\xaf", &info) => 0; + assert(strcmp(info.name, "\xaf") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "\xe0/\xbf", &info) => 0; + assert(strcmp(info.name, "\xbf") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "\xe0/\xcf", &info) => 0; + assert(strcmp(info.name, "\xcf") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "\xe0/\xdf", &info) => 0; + assert(strcmp(info.name, "\xdf") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "\xe0/\xef", &info) => 0; + assert(strcmp(info.name, "\xef") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "\xe0/\xff", &info) => 0; + assert(strcmp(info.name, "\xff") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfsr_stat(&lfs, "\xc0/\xa0", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "\xc0/\xb0", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "\xc0/\xc0", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "\xc0/\xd0", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "\xc0/\xe0", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "\xc0/\xf0", &info) => LFS_ERR_NOENT; + + // remove paths + lfsr_remove(&lfs, "\xe0/\xaf") => 0; + lfsr_remove(&lfs, "\xe0/\xbf") => 0; + lfsr_remove(&lfs, "\xe0/\xcf") => 0; + lfsr_remove(&lfs, "\xe0/\xdf") => 0; + lfsr_remove(&lfs, "\xe0/\xef") => 0; + lfsr_remove(&lfs, "\xe0/\xff") => 0; + + // stat paths + lfsr_stat(&lfs, "\xe0/\xaf", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "\xe0/\xbf", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "\xe0/\xcf", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "\xe0/\xdf", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "\xe0/\xef", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "\xe0/\xff", &info) => LFS_ERR_NOENT; + + lfsr_unmount(&lfs) => 0; +''' + +# test with only "\xff" characters +# +# Don't do this! These filenames are not utf8 and will probably break +# external tools. +# +[cases.test_paths_oopsallffs] +defines.DIR = [false, true] +code = ''' + lfs_t lfs; + lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; + lfsr_mount(&lfs, LFS_F_RDWR, CFG) => 0; + + // create paths + lfsr_mkdir(&lfs, "\xff") => 0; + if (DIR) { + lfsr_mkdir(&lfs, "\xff/\xff") => 0; + lfsr_mkdir(&lfs, "\xff/\xff\xff") => 0; + lfsr_mkdir(&lfs, "\xff/\xff\xff\xff") => 0; + lfsr_mkdir(&lfs, "\xff/\xff\xff\xff\xff") => 0; + lfsr_mkdir(&lfs, "\xff/\xff\xff\xff\xff\xff") => 0; + lfsr_mkdir(&lfs, "\xff/\xff\xff\xff\xff\xff\xff") => 0; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "\xff/\xff", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\xff/\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\xff/\xff\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + lfsr_file_close(&lfs, &file) => 0; + } + + // stat paths + struct lfs_info info; + lfsr_stat(&lfs, "\xff/\xff", &info) => 0; + assert(strcmp(info.name, "\xff") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "\xff/\xff\xff", &info) => 0; + assert(strcmp(info.name, "\xff\xff") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "\xff/\xff\xff\xff", &info) => 0; + assert(strcmp(info.name, "\xff\xff\xff") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "\xff/\xff\xff\xff\xff", &info) => 0; + assert(strcmp(info.name, "\xff\xff\xff\xff") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "\xff/\xff\xff\xff\xff\xff", &info) => 0; + assert(strcmp(info.name, "\xff\xff\xff\xff\xff") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "\xff/\xff\xff\xff\xff\xff\xff", &info) => 0; + assert(strcmp(info.name, "\xff\xff\xff\xff\xff\xff") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + // file open paths, only works on files! + if (DIR) { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "\xff/\xff", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "\xff/\xff\xff", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "\xff/\xff\xff\xff", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff\xff", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff\xff\xff", + LFS_O_RDONLY) => LFS_ERR_ISDIR; + + lfsr_file_open(&lfs, &file, "\xff/\xff", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "\xff/\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "\xff/\xff\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + lfsr_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR; + + lfsr_file_open(&lfs, &file, "\xff/\xff", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "\xff/\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "\xff/\xff\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + } else { + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "\xff/\xff", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\xff/\xff\xff", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\xff/\xff\xff\xff", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff\xff", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff\xff\xff", + LFS_O_RDONLY) => 0; + lfsr_file_close(&lfs, &file) => 0; + + lfsr_file_open(&lfs, &file, "\xff/\xff", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\xff/\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\xff/\xff\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + lfsr_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT) => 0; + lfsr_file_close(&lfs, &file) => 0; + + lfsr_file_open(&lfs, &file, "\xff/\xff", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "\xff/\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "\xff/\xff\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + lfsr_file_open(&lfs, &file, "\xff/\xff\xff\xff\xff\xff\xff", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST; + } + + // dir open paths, only works on dirs! + if (DIR) { + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "\xff/\xff") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "\xff/\xff\xff") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "\xff/\xff\xff\xff") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "\xff/\xff\xff\xff\xff") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "\xff/\xff\xff\xff\xff\xff") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + lfsr_dir_open(&lfs, &dir, "\xff/\xff\xff\xff\xff\xff\xff") => 0; + lfsr_dir_close(&lfs, &dir) => 0; + } else { + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, "\xff/\xff") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "\xff/\xff\xff") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "\xff/\xff\xff\xff") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "\xff/\xff\xff\xff\xff") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "\xff/\xff\xff\xff\xff\xff") => LFS_ERR_NOTDIR; + lfsr_dir_open(&lfs, &dir, "\xff/\xff\xff\xff\xff\xff\xff") => LFS_ERR_NOTDIR; + } + + // rename paths + lfsr_mkdir(&lfs, "\xff\xff") => 0; + lfsr_rename(&lfs, + "\xff/\xff", + "\xff\xff/\xff\xff\xff\xff\xff\xff") => 0; + lfsr_rename(&lfs, + "\xff/\xff\xff", + "\xff\xff/\xff\xff\xff\xff\xff\xff\xff") => 0; + lfsr_rename(&lfs, + "\xff/\xff\xff\xff", + "\xff\xff/\xff\xff\xff\xff\xff\xff\xff\xff") => 0; + lfsr_rename(&lfs, + "\xff/\xff\xff\xff\xff", + "\xff\xff/\xff\xff\xff\xff\xff\xff\xff\xff\xff") => 0; + lfsr_rename(&lfs, + "\xff/\xff\xff\xff\xff\xff", + "\xff\xff/\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff") => 0; + lfsr_rename(&lfs, + "\xff/\xff\xff\xff\xff\xff\xff", + "\xff\xff/\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff") => 0; + + // stat paths + lfsr_stat(&lfs, "\xff\xff/\xff\xff\xff\xff\xff\xff", &info) => 0; + assert(strcmp(info.name, "\xff\xff\xff\xff\xff\xff") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "\xff\xff/\xff\xff\xff\xff\xff\xff\xff", &info) => 0; + assert(strcmp(info.name, "\xff\xff\xff\xff\xff\xff\xff") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "\xff\xff/\xff\xff\xff\xff\xff\xff\xff\xff", &info) => 0; + assert(strcmp(info.name, "\xff\xff\xff\xff\xff\xff\xff\xff") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "\xff\xff/\xff\xff\xff\xff\xff\xff\xff\xff\xff", &info) => 0; + assert(strcmp(info.name, "\xff\xff\xff\xff\xff\xff\xff\xff\xff") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "\xff\xff/\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff", &info) => 0; + assert(strcmp(info.name, "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + lfsr_stat(&lfs, "\xff\xff/\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff", &info) => 0; + assert(strcmp(info.name, "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff") == 0); + assert(info.type == ((DIR) ? LFS_TYPE_DIR : LFS_TYPE_REG)); + + lfsr_stat(&lfs, "\xff/\xff", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "\xff/\xff\xff", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "\xff/\xff\xff\xff", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "\xff/\xff\xff\xff\xff", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "\xff/\xff\xff\xff\xff\xff", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "\xff/\xff\xff\xff\xff\xff\xff", &info) => LFS_ERR_NOENT; + + // remove paths + lfsr_remove(&lfs, "\xff\xff/\xff\xff\xff\xff\xff\xff") => 0; + lfsr_remove(&lfs, "\xff\xff/\xff\xff\xff\xff\xff\xff\xff") => 0; + lfsr_remove(&lfs, "\xff\xff/\xff\xff\xff\xff\xff\xff\xff\xff") => 0; + lfsr_remove(&lfs, "\xff\xff/\xff\xff\xff\xff\xff\xff\xff\xff\xff") => 0; + lfsr_remove(&lfs, "\xff\xff/\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff") => 0; + lfsr_remove(&lfs, "\xff\xff/\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff") => 0; + + // stat paths + lfsr_stat(&lfs, "\xff\xff/\xff\xff\xff\xff\xff\xff", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "\xff\xff/\xff\xff\xff\xff\xff\xff\xff", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "\xff\xff/\xff\xff\xff\xff\xff\xff\xff\xff", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "\xff\xff/\xff\xff\xff\xff\xff\xff\xff\xff\xff", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "\xff\xff/\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff", &info) => LFS_ERR_NOENT; + lfsr_stat(&lfs, "\xff\xff/\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff", &info) => LFS_ERR_NOENT; + + lfsr_unmount(&lfs) => 0; +'''