static int _validate_cs_(nspace *vol, uint32 cluster, uint32 sector) { if (sector < 0) return -1; if ((vol->fat_bits != 32) && IS_FIXED_ROOT(cluster)) { // fat12 or fat16 root if (sector >= vol->root_sectors) return -1; return 0; } if (sector >= vol->sectors_per_cluster) return -1; if (!IS_DATA_CLUSTER(cluster)) return -1; return 0; }
static status_t get_next_dirent(nspace *vol, vnode *dir, struct diri *iter, ino_t *vnid, char *filename, int len) { struct _dirent_info_ info; status_t result; do { result = _next_dirent_(iter, &info, filename, len); if (result < 0) return result; // only hide volume label entries in the root directory } while ((info.mode & FAT_VOLUME) && (dir->vnid == vol->root_vnode.vnid)); if (!strcmp(filename, ".")) { // assign vnode based on parent if (vnid) *vnid = dir->vnid; } else if (!strcmp(filename, "..")) { // assign vnode based on parent of parent if (vnid) *vnid = dir->dir_vnid; } else { if (vnid) { ino_t loc = (IS_DATA_CLUSTER(info.cluster)) ? GENERATE_DIR_CLUSTER_VNID(dir->vnid, info.cluster) : GENERATE_DIR_INDEX_VNID(dir->vnid, info.sindex); bool added_to_vcache = false; /* if it matches a loc in the lookup table, we are done. */ result = vcache_loc_to_vnid(vol, loc, vnid); if (result == ENOENT) { /* ...else check if it matches any vnid's in the lookup table */ if (find_vnid_in_vcache(vol, loc) == B_OK) { /* if it does, create a random one since we can't reuse * existing vnid's */ *vnid = generate_unique_vnid(vol); /* and add it to the vcache */ if ((result = add_to_vcache(vol, *vnid, loc)) < 0) return result; added_to_vcache = true; } else { /* otherwise we are free to use it */ *vnid = loc; } } else if (result != B_OK) { dprintf("get_next_dirent: unknown error (%s)\n", strerror(result)); return result; } if (info.mode & FAT_SUBDIR) { if (dlist_find(vol, info.cluster) == -1LL) { if ((result = dlist_add(vol, *vnid)) < 0) { if (added_to_vcache) remove_from_vcache(vol, *vnid); return result; } } } } } DPRINTF(2, ("get_next_dirent: found %s (vnid %Lx)\n", filename, vnid != NULL ? *vnid : (ino_t)0)); return B_NO_ERROR; }