int ext2_read_directory(struct filesystem *fs, int dino, char *f) { /* read the directory inode in */ struct ext2_inode *inode = kmalloc(sizeof(*inode)); ext2_read_inode(fs, inode, dino); if (inode->type & 0x4000 == 0) return -ENOTDIR; /* the block pointers contain some 'struct ext2_dir's, so parse */ void *bbuf = kmalloc(EXT2_PRIV(fs)->blocksize); for (int i = 0; i < 12; i++) { ext2_read_block(fs, bbuf, inode->dbp[i]); struct ext2_dir *d = (void *)bbuf; if (d->size == 0 || d->namelength == 0) break; int r = 0; while (r < EXT2_PRIV(fs)->blocksize) { if (strncmp(&d->reserved + 1, f, d->namelength) == 0) { int k = d->inode; new_free(bbuf); return k; } r += d->size; if (d->size == 0 || d->namelength == 0) { goto c1; } d = (struct ext2_dir *)((uintptr_t)d + d->size); } c1:; } new_free(bbuf); return -ENOENT; }
struct fs_Inode* fs_inode_open(size_t inode) { for (size_t i = 0; i < MAX_OPEN_INODES; i++) { if (inodeTable[i]) { if (inodeTable[i]->refCount <= 0) { kprintf("Inode %u in entry %u is broken.\n", inodeTable[i]->number, i); while (1); } } } for (size_t i = 0; i < MAX_OPEN_INODES; i++) { if (inodeTable[i] != NULL && inodeTable[i]->number == inode) { inodeTable[i]->refCount++; return inodeTable[i]; } } struct fs_Inode* node = ext2_read_inode(fs, inode); node->extra = NULL; if (node == NULL) { return NULL; } node->refCount = 1; for (size_t i = 0; i < MAX_OPEN_INODES; i++) { if (inodeTable[i] == NULL) { inodeTable[i] = node; return node; } } free_inode(node); return NULL; }
int sys_open(char* path) { u32 fd; struct file* fp; struct open_file* of; if (!(fp = path_to_file(path))) { // printk("DEBUG: sys_open(): can't open %s\n", path); return -1; } // printk("DEBUG: sys_open(): process[%d] opening file %s\n", current->pid, fp->name); fp->opened++; if (!fp->inode) fp->inode = ext2_read_inode(fp->disk, fp->inum); /* Lecture du fichier */ fp->mmap = ext2_read_file(fp->disk, fp->inode); /* * Recherche d'un descripteur libre. */ fd = 0; if (current->fd == 0) { current->fd = (struct open_file *) malloc(sizeof(struct open_file)); current->fd->file = fp; current->fd->ptr = 0; current->fd->next = 0; } else { of = current->fd; while (of->file && of->next) { of = of->next; fd++; } if (of->file == 0) /* Reuse old descriptor */ { of->file = fp; of->ptr = 0; } else /* Use new one */ { of->next = (struct open_file *) malloc(sizeof(struct open_file)); of->next->file = fp; of->next->ptr = 0; of->next->next = 0; fd++; } } return fd; }
void ext2fs_dump_info( char *path ){ ext2_device_t *e2 = ext2_create_device( path ); printf( "ext version: %d.%d\n", e2->sprblk->maj_version, e2->sprblk->min_version ); printf( "n_inodes: %d, n_blocks: %d, reserved blocks: %d\n", e2->sprblk->n_inodes, e2->sprblk->n_blocks, e2->sprblk->su_reserved ); printf( "free_blocks: %d, free_inodes: %d, superblock: %d\n", e2->sprblk->free_blocks, e2->sprblk->free_inodes, e2->sprblk->sprblk_block ); printf( "block size: %d, fragment size: %d, blocks per group: %d\n", 1024 << e2->sprblk->block_size, 1024 << e2->sprblk->frag_size, e2->sprblk->n_block_block_grp ); printf( "First free inode: %d, sizeof inode: %d\n", e2->esprblk->first_free_inode, e2->esprblk->inode_size ); printf( "last path: \"%s\"\n", e2->esprblk->last_path ); printf( "first block group descript, inode table: %d\n", e2->blkdesc->inode_table_addr ); ext2_inode_t *inode = knew( char[ e2->esprblk->inode_size ]); ext2_get_inode( e2, 2, inode ); printf( "Got inode, links: %d, 1st block: %d\n", inode->hard_links, inode->d_ptr[0] ); char *data = knew( char[ e2->block_size * 5 ] ); ext2_read_inode( e2, inode, data, e2->block_size ); printf( "root listing:\n" ); ext2_dirent_t *dirent = (ext2_dirent_t *)data; while( *(char *)dirent ){ printf( "name: \"%s\", inode: %d\n", &dirent->name, dirent->inode ); dirent = (ext2_dirent_t *)(((unsigned long)dirent) + dirent->size ); } //ext2_get_inode( e2, 2049, inode ); //ext2_read_inode( e2, inode, data, e2->block_size * 3, 0 ); //ext2_read_inode( e2, inode, data, 4279 ); //printf( "size: %d\n", inode->low_size ); //printf( "%s\n", data ); //printf( "listing asdf:\n" ); /* dirent = (ext2_dirent_t *)data; while( *(char *)dirent ){ printf( "name: \"%s\", inode: %d\n", &dirent->name, dirent->inode ); dirent = (ext2_dirent_t *)(((unsigned long)dirent) + dirent->size ); } */ kfree( data ); kfree( e2->sprblk ); kfree( e2->blkdesc ); kfree( e2 ); return; }
/* read in the dir, look for the entry */ static int ext2_dir_lookup(ext2_t *ext2, struct ext2_inode *dir_inode, const char *name, inodenum_t *inum) { uint file_blocknum; int err; uint8_t *buf; size_t namelen = strlen(name); if (!S_ISDIR(dir_inode->i_mode)) return ERR_NOT_DIR; buf = malloc(EXT2_BLOCK_SIZE(ext2->sb)); file_blocknum = 0; for (;;) { /* read in the offset */ err = ext2_read_inode(ext2, dir_inode, buf, file_blocknum * EXT2_BLOCK_SIZE(ext2->sb), EXT2_BLOCK_SIZE(ext2->sb)); if (err <= 0) { free(buf); return -1; } /* walk through the directory entries, looking for the one that matches */ struct ext2_dir_entry_2 *ent; uint pos = 0; while (pos < EXT2_BLOCK_SIZE(ext2->sb)) { ent = (struct ext2_dir_entry_2 *)&buf[pos]; LTRACEF("ent %d:%d: inode 0x%x, reclen %d, namelen %d\n", file_blocknum, pos, LE32(ent->inode), LE16(ent->rec_len), ent->name_len/* , ent->name*/); /* sanity check the record length */ if (LE16(ent->rec_len) == 0) break; if (ent->name_len == namelen && memcmp(name, ent->name, ent->name_len) == 0) { // match *inum = LE32(ent->inode); LTRACEF("match: inode %d\n", *inum); free(buf); return 1; } pos += ROUNDUP(LE16(ent->rec_len), 4); } file_blocknum++; /* sanity check the directory. 4MB should be enough */ if (file_blocknum > 1024) { free(buf); return -1; } } }
/* read in the dir, look for the entry */ int ext2_dirent_lookup(ext2_t *ext2, struct ext2_inode *dir_inode, const char **name, unsigned index) { uint file_blocknum; int err; uint8_t *buf; unsigned curpos = 0; if (!S_ISDIR(dir_inode->i_mode)) return ERR_NOT_DIR; buf = malloc(EXT2_BLOCK_SIZE(ext2->sb)); file_blocknum = 0; for (;;) { /* read in the offset */ err = ext2_read_inode(ext2, dir_inode, buf, file_blocknum * EXT2_BLOCK_SIZE(ext2->sb), EXT2_BLOCK_SIZE(ext2->sb)); if (err <= 0) { free(buf); if (err == 0) return 0; else return -1; } /* walk through the directory entries, looking for the one that matches */ struct ext2_dir_entry_2 *ent; uint pos = 0; while (pos < EXT2_BLOCK_SIZE(ext2->sb)) { ent = (struct ext2_dir_entry_2 *)&buf[pos]; LTRACEF("ent %d:%d: inode 0x%x, reclen %d, namelen %d\n", file_blocknum, pos, LE32(ent->inode), LE16(ent->rec_len), ent->name_len/* , ent->name*/); /* sanity check the record length */ if (LE16(ent->rec_len) == 0) break; if (strncmp(ent->name, ".", ent->name_len) != 0 && strncmp(ent->name, "..", ent->name_len) != 0) { if (curpos == index) { *name = malloc(ent->name_len + 1); memcpy(*name, ent->name, ent->name_len); *((char *)(*name) + ent->name_len) = 0; return 1; } else { curpos++; } } pos += ROUNDUP(LE16(ent->rec_len), 4); } file_blocknum++; /* sanity check the directory. 4MB should be enough */ if (file_blocknum > 1024) { free(buf); return -1; } } return -1; }
int ext2_find_file(struct ext2_desc *desc, const char *pathname, struct ext2_inode *inode) { struct ext2_directory_entry entry; char path_temp[1024], *filename, *p; text_copy(path_temp, pathname); filename = p = path_temp; entry.inode = 2; entry.file_type = EXT_FILE_TYPE_DIRECTORY; while (1) { int ret; ssize_t rdlen; rdlen = ext2_read_inode(desc, entry.inode, inode); if (rdlen < 0) { print_error("ext2_read_inode"); return rdlen; } #if CAVAN_EXT2_DEBUG show_ext2_inode(inode); #endif while (*filename == '/') { filename++; } if (*filename == 0) { break; } if (entry.file_type != EXT_FILE_TYPE_DIRECTORY) { ERROR_RETURN(ENOENT); } for (p = filename; *p && *p != '/'; p++); *p = 0; if (inode->flags & EXT2_INODE_FLAG_EXTENTS) { ret = ext4_find_file_base(desc, filename, (struct ext4_extent_header *) inode->block, &entry); } else { ret = ext2_find_file_base(desc, filename, inode->block, inode->blocks, &entry); } if (ret < 0) { ERROR_RETURN(ENOENT); } filename = p + 1; } return 0; }
bool ext2_add_entry( PEXT2_FILESYS Ext2Sys, ULONG parent, ULONG inode, int filetype, char *name ) { PEXT2_DIR_ENTRY2 dir = NULL, newdir = NULL; EXT2_INODE parent_inode; ULONG dwRet; char *buf; int rec_len; bool bRet = false; rec_len = EXT2_DIR_REC_LEN(strlen(name)); if (!ext2_load_inode(Ext2Sys, parent, &parent_inode)) { return false; } buf = (char *)RtlAllocateHeap(RtlGetProcessHeap(), 0, parent_inode.i_size); if (!ext2_read_inode(Ext2Sys, parent, 0, buf, parent_inode.i_size, &dwRet)) { return false; } dir = (PEXT2_DIR_ENTRY2) buf; while ((char *)dir < buf + parent_inode.i_size) { if ((dir->inode == 0 && dir->rec_len >= rec_len) || (dir->rec_len >= dir->name_len + rec_len) ) { if (dir->inode) { newdir = (PEXT2_DIR_ENTRY2) ((PUCHAR)dir + EXT2_DIR_REC_LEN(dir->name_len)); newdir->rec_len = dir->rec_len - EXT2_DIR_REC_LEN(dir->name_len); dir->rec_len = EXT2_DIR_REC_LEN(dir->name_len); dir = newdir; } dir->file_type = filetype; dir->inode = inode; dir->name_len = strlen(name); memcpy(dir->name, name, strlen(name)); bRet = true; break; } dir = (PEXT2_DIR_ENTRY2) (dir->rec_len + (PUCHAR) dir); } if (bRet) return ext2_write_inode(Ext2Sys, parent, 0, buf, parent_inode.i_size, &dwRet); return bRet; }