int tm_fs_rename (tm_fs_ent* root, const char* oldname, const char* newname) { int r = 0; // Lookup old file tm_fs_ent* oldent = 0; r = tm_fs_lookup(root, oldname, &oldent); if (r != 0) { return r; } // Lookup and possibly new file location. tm_fs_ent* newdir = 0; r = tm_fs_lookup(root, newname, &newdir); if (r == 0) { tm_fs_ent* overwritten = newdir; newdir = overwritten->parent; tm_fs_destroy(overwritten); } else if (r == -ENOENT && newdir != 0) { // noop, folder exists } else { return -ENOENT; } tm_fs_dir_remove(oldent->parent, oldent); tm_fs_dir_append(newdir, tm_fs_basename(newname), oldent); return 0; }
int tm_fs_open(tm_fs_file_handle* /* -> ~<'s> */ out, tm_fs_ent* /* &'s */ root, const char* /* & */ pathname, unsigned flags) { tm_fs_ent* ent = 0; int r = tm_fs_lookup(root, pathname, &ent); if ((flags & TM_CREAT) && r == -ENOENT && ent != 0) { tm_fs_ent* parent = ent; ent = tm_fs_raw_file_create(); r = tm_fs_dir_append(parent, pathname, ent); if (r) { tm_fs_destroy(ent); return r; } } else if (r != 0) { return r; } else if (flags & TM_EXCL) { return -EEXIST; } switch (ent->type) { case VFS_TYPE_RAW_FILE: if (flags & TM_TRUNC) { free(ent->file.data); ent->file.length = 0; ent->file.data = 0; } out->ent = ent; out->position = 0; return 0; case VFS_TYPE_DIR: return -EISDIR; default: return -EINVAL; } }
int tm_fs_type (tm_fs_ent* root, const char* path) { tm_fs_ent* ent = 0; int r = tm_fs_lookup(root, path, &ent); if (r == 0) { return ent->type; } return r; }
int tm_fs_lookup(tm_fs_ent* /*&mut 'fs*/ dir, const char* /* & */ path, tm_fs_ent** out) { if (path == 0) { if (out) *out = dir; return 0; } if (out) *out = NULL; if (dir->type != VFS_TYPE_DIR) { return -ENOTDIR; } while (path[0] == '/') path++; // Strip leading slashes char* next = strchr(path, '/'); if (path[0] == 0 || str_match_range(path, next, ".")) { return tm_fs_lookup(dir, next, out); } else if (str_match_range(path, next, "..")) { if (dir->parent) { return tm_fs_lookup(dir->parent, next, out); } else { return -ENOENT; } } else { for (unsigned i=0; i<dir->dir.num_entries; i++) { tm_fs_direntry* entry = &dir->dir.entries[i]; if (str_match_range(path, next, entry->name)) { return tm_fs_lookup(entry->ent, next, out); } } if (next) { while (next[0] == '/') next++; // Strip trailing slashes } if (next == 0 || next[0] == 0) { // No more path components; this is the parent of the requested directory if (out) *out = dir; } return -ENOENT; } }
int tm_fs_insert(tm_fs_ent* root, const char* path, tm_fs_ent* ent) { tm_fs_ent* parent = 0; int r = tm_fs_lookup(root, path, &parent); if (r == -ENOENT && parent != 0) { return tm_fs_dir_append(parent, path, ent); } else if (r == 0) { return -EEXIST; } return r; }
int tm_fs_dir_open(tm_fs_dir_handle* out, tm_fs_ent* root, const char* pathname) { tm_fs_ent* ent = 0; int r = tm_fs_lookup(root, pathname, &ent); if (r != 0) { return r; } switch (ent->type) { case VFS_TYPE_DIR: out->ent = ent; out->position = 0; return 0; default: return -ENOTDIR; } }
int tm_fs_dir_create(tm_fs_ent* root, const char* path) { tm_fs_ent* ent = 0; int r = tm_fs_lookup(root, path, &ent); if (r == -ENOENT && ent != 0) { // Directory doesn't exist, but its parent does tm_fs_ent* dir = tm_fs_dir_create_entry(); return tm_fs_dir_append(ent, path, dir); } else if (r == 0) { if (ent->type == VFS_TYPE_DIR) { // like mkdir -p, but only for one level return 0; } else { return -EEXIST; } } return r; }
static int l_tm_fs_destroy (lua_State* L) { const char *pathname = (const char *) colony_toutf8(L, 1); #ifdef TM_FS_vfs tm_fs_ent* ent = NULL; int r = tm_fs_lookup(tm_fs_root, pathname, &ent); if (r != ENOENT) { ent->file.data_owned = 0; // ent->file.data = malloc(0); tm_fs_destroy(ent); } int ret = -r; #else int ret = tm_fs_destroy(pathname); #endif lua_pushnumber(L, ret); return 1; }