/** * Remove the target file or link */ void ext2_rm(struct ext2_disk *disk, const char *target_file_name) { // Read info about the containing directory char *last_segment; uint32_t container_inode; struct ext2_inode *containing_directory = ext2_traverse_path(disk, NULL, target_file_name, &last_segment, &container_inode); struct ext2_directory_entry *entry; if ((entry = ext2_read_entry_from_directory(disk, containing_directory, last_segment)) == NULL) { // File does not exist errx(1, "File with name %s does not exist", last_segment); } else if (IS_DIRECTORY(ext2_get_inode(disk, 0, entry->inode_addr))) { // Target is a directory errx(1, "Cannot remove directory %s", last_segment); } else { // Save the inode number uint32_t inode_addr = entry->inode_addr; // Remove the directory entry by clearing its fields entry->inode_addr = 0; entry->size = 0; entry->name_length = 0; entry->type_indicator = 0; entry->name = 0; // Decrement the hard link count if (--ext2_get_inode(disk, 0, inode_addr)->num_links == 0) // No more hard links point to the inode; free the inode and data blocks ext2_free_inode(disk, inode_addr); } }
/* * Copy */ void copy1( struct ext2_filesystem *fs, char *pathS, char *nameS, char *pathD, char *nameD ) { struct ext2_dir_entry_2 *direntS = ext2_get_dirent_from_path( fs, pathS, nameS ); if (!direntS) { printf("copy: %s%s: file not found\n", pathS, nameS); return; } struct ext2_dir_entry_2 *parentDirentD = ext2_get_dirent_from_path( fs, pathD, "." ); if (!parentDirentD) { printf("copy: %s: directory not found\n", pathD); return; } struct ext2_inode *parentInode = ext2_get_inode( fs, parentDirentD->inode ); if (!parentInode) { printf("copy: %d: inode not found\n", parentDirentD->inode); return; } struct ext2_inode *inodeS = ext2_get_inode( fs, direntS->inode ); if (!inodeS) { printf("copy: %d: inode not found\n", direntS->inode); return; } uint32 newInodeNum = ext2_inode_alloc( fs ); if (!newInodeNum) { printf("copy: no new inode available\n"); return; } struct ext2_inode *newInode = ext2_get_inode( fs, newInodeNum ); if (!newInode) return; newInode->i_mode = inodeS->i_mode; newInode->i_size = 0; struct ext2_dir_entry_2 *newDirent = ext2_dirent_alloc( fs, parentInode ); if (!newDirent) { printf("copy: no new dirents available\n"); return; } newDirent->inode = newInodeNum; newDirent->next_dirent = 0; newDirent->name_len = strnlen( nameD, EXT2_NAME_LEN ); newDirent->filetype = direntS->filetype; memcpy( newDirent->name, nameD, strnlen( nameD, EXT2_NAME_LEN ) ); char buff[inodeS->i_size]; int bytesRead = ext2_read_dirent( fs, direntS, buff, 0, inodeS->i_size ); int bytesWritten = ext2_write_file_by_inode( fs, newDirent, buff, 0, bytesRead ); }
struct ext2_inode *ext2_create_inode(struct ext2_disk *disk, struct ext2_inode *cwd, const char *last_segment, uint32_t *inode_addr) { // Find a free inode via the usage bitmap if ((*inode_addr = _get_free_inode_addr(disk)) == 0) errx(1, "Could not find a free inode"); return ext2_get_inode(disk, 0, *inode_addr); }
unsigned int ext2_seek_name(ext2_VOLUME *volume, const char *name) { struct ext2_inode inode; int ret; unsigned int ino; off_t index; struct ext2_dir_entry_2 entry; ino = EXT2_ROOT_INO; while(1) { while (*name == '\\') name++; if (!*name) break; ret = ext2_get_inode(volume, ino, &inode); if (ret == -1) return 0; index = 0; while (1) { index = ext2_dir_entry(volume, &inode, index, &entry); if (index == -1) return 0; ret = strncmp(name, entry.name, entry.name_len); if (ret == 0 && (name[entry.name_len] == 0 || name[entry.name_len] == '\\')) { ino = entry.inode; break; } } name += entry.name_len; } return ino; }
int ext2_fsync(struct file *file, int datasync) { int ret; struct inode *inode = file->f_mapping->host; ino_t ino = inode->i_ino; struct super_block *sb = inode->i_sb; struct address_space *sb_mapping = sb->s_bdev->bd_inode->i_mapping; struct buffer_head *bh; struct ext2_inode *raw_inode; ret = generic_file_fsync(file, datasync); if (ret == -EIO || test_and_clear_bit(AS_EIO, &sb_mapping->flags)) { /* We don't really know where the IO error happened... */ ext2_error(sb, __func__, "detected IO error when writing metadata buffers"); return -EIO; } raw_inode = ext2_get_inode(sb, ino, &bh); if (IS_ERR(raw_inode)) return -EIO; sync_dirty_buffer(bh); if (buffer_req(bh) && !buffer_uptodate(bh)) { printk ("IO error syncing ext2 inode [%s:%08lx]\n", sb->s_id, (unsigned long) ino); ret = -EIO; } brelse (bh); return ret; }
struct file *filesys_open (const char *name){ struct block *block = NULL; struct directory *file_desc = NULL; struct inode *file_ino = NULL; struct file *file = NULL; ASSERT(name != NULL); // look up device block = block_get_role (BLOCK_FILESYS); // look up file if(block != NULL) file_desc = dir_lookup(block,name); // look up inode if(file_desc != NULL) file_ino = ext2_get_inode(block,file_desc->inode); // open file if(file_ino != NULL) file = file_open(block,file_desc,file_ino); return file; }
/** * Read the directory containing the item with the given path (i.e. traverse each path segment until the last), * starting at the given current working directory. * Exit with an error if a directory along the path could not be found. */ struct ext2_inode *ext2_traverse_path(struct ext2_disk *disk, struct ext2_inode *cwd, const char *file_path, char **last_segment, uint32_t *container_inode) { if (file_path[0] == '/') { // Start from the root path struct ext2_inode *root_directory = ext2_get_inode(disk, 0, 2); *container_inode = 2; if (file_path[1] == '\0') { // Path is just "/"; return the root directory *last_segment = ""; return root_directory; } // Otherwise, recurse using root_directory as cwd return ext2_traverse_path(disk, root_directory, file_path + 1, last_segment, container_inode); } else { // file_path is relative to cwd; search for first path segment in cwd // Copy file_path into str char *str = malloc(strlen(file_path) + 1); strcpy(str, file_path); // Get the first path segment from str char *segment = strsep(&str, "/"); if (str == NULL) { // `segment` is the last path segment; return this cwd *last_segment = segment; return cwd; } // Find the directory inode in this directory struct ext2_directory_entry *entry_found = ext2_read_entry_from_directory(disk, cwd, segment); *container_inode = entry_found->inode_addr; struct ext2_inode *inode_found = ext2_get_inode(disk, 0, entry_found->inode_addr); if (inode_found == NULL) { // Could not find inode in directory errx(1, "Could not find file or directory %s", segment); } else if (IS_DIRECTORY(inode_found)) { // Found a directory, and is not last path segment // Recurse with file_found as cwd return ext2_traverse_path(disk, inode_found, str, last_segment, container_inode); } else { errx(1, "File %s is not a directory", segment); } } }
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; }
/* * Create a new empty file of the given name in the given path */ void touch1( struct ext2_filesystem *fs, char *path, char *name ) { struct ext2_dir_entry_2 *dir = ext2_get_dirent_from_path( fs, path, "." ); if (!dir) { printf("touch: %s: No such file or directory\n",path); return; } struct ext2_inode *dirInode = ext2_get_inode( fs, dir->inode ); if (!dirInode) { printf("touch: %d: No such inode\n", dir->inode); return; } uint32 newInodeNum = ext2_inode_alloc( fs ); if (!newInodeNum) { printf("touch: No inode available\n"); return; } struct ext2_inode *newInode = ext2_get_inode( fs, newInodeNum ); if (!newInode) { printf("touch: %d: No such inode\n", newInodeNum); return; } newInode->i_mode = EXT2_S_IFREG; newInode->i_size = 0; struct ext2_dir_entry_2 *newDirent = ext2_dirent_alloc( fs, dirInode ); if (!newDirent) { printf("touch: No dirent available\n"); return; } newDirent->inode = newInodeNum; memcpy( newDirent->name, name, strnlen( name, EXT2_NAME_LEN ) ); newDirent->next_dirent = 0; newDirent->name_len = strnlen( name, EXT2_NAME_LEN ); newDirent->filetype = EXT2_FT_REG_FILE; }
static struct inode *ext2_iget_by_inr(struct fs_info *fs, uint32_t inr) { const struct ext2_inode *e_inode; struct inode *inode; e_inode = ext2_get_inode(fs, inr); if (!e_inode) return NULL; if (!(inode = alloc_inode(fs, inr, sizeof(struct ext2_pvt_inode)))) return NULL; fill_inode(inode, e_inode); return inode; }
int ext2_write_directory_data(struct ext2_disk *disk, uint32_t containing_inode_addr, struct ext2_directory_entry *entry) { struct ext2_inode *inode = ext2_get_inode(disk, 0, entry->inode_addr); // Write entries for "." and ".." struct ext2_directory_entry *current_entry = _next_directory_entry(disk, inode->direct_blocks[0], NULL); struct ext2_directory_entry *upper_entry = _next_directory_entry(disk, inode->direct_blocks[0], current_entry); current_entry->inode_addr = entry->inode_addr; current_entry->name_length = 1; strcpy(¤t_entry->name, "."); upper_entry->inode_addr = containing_inode_addr; upper_entry->name_length = 2; strcpy(&upper_entry->name, ".."); return sizeof(current_entry) + 1 + sizeof(upper_entry) + 2; }
static struct directory *dir_get_root(struct block *d){ struct inode *root_ino; struct directory *root; ASSERT(d != NULL); // get root inode root_ino = ext2_get_inode(d,EXT2_ROOT_INO); // allocate memory root = kmalloc(root_ino->i_size); if(root == NULL) return NULL; // read entire file inode_read_at(d,root_ino,root,root_ino->i_size,0); return root; }
/* * Remove a directory */ void rmdir1( struct ext2_filesystem *fs, char *path, char *dirName ) { struct ext2_dir_entry_2 *parentDirent = ext2_get_dirent_from_path( fs, path, "." ); struct ext2_dir_entry_2 *dirent = ext2_get_dirent_from_path( fs, path, dirName ); ext2_dirent_dealloc( fs, dirent, parentDirent->inode ); struct ext2_inode *inode = ext2_get_inode( fs, dirent->inode ); struct ext2_dir_entry_2 *first_dirent = ext2_get_first_dirent( fs, inode ); struct ext2_dir_entry_2 *curr_dirent = first_dirent; while( curr_dirent ) { ext2_inode_dealloc( fs, curr_dirent->inode ); curr_dirent = ext2_get_next_dirent( fs, curr_dirent ); } ext2_inode_dealloc( fs, first_dirent->inode ); }
/* * Print the contents of a file */ void cat1( struct ext2_filesystem *fs, char *path, char *name ) { struct ext2_dir_entry_2 *file = ext2_get_dirent_from_path( fs, path, name ); if (!file) { printf("cat: %s: No such file or directory\n",path); return; } struct ext2_inode *inode = ext2_get_inode( fs, file->inode ); if (!inode) { printf("cat: %d: No such inode\n", file->inode); return; } char buffer[inode->i_size + 1]; int read = ext2_read_dirent( fs, file, buffer, 0, inode->i_size ); buffer[read] = 0; printf( "%s\n", buffer ); }
ext2_inodetable_t * ext2_finddir( ext2_inodetable_t * rnode, char * name ) { void * block; ext2_dir_t * direntry = NULL; block = (void *)ext2_get_block((rnode->block[0])); uint32_t dir_offset; dir_offset = 0; /* * Look through the requested entries until we find what we're looking for */ while (dir_offset < rnode->size) { ext2_dir_t * d_ent = (ext2_dir_t *)((uintptr_t)block + dir_offset); char * dname = malloc(sizeof(char) * (d_ent->name_len + 1)); memcpy(dname, &d_ent->name, d_ent->name_len); dname[d_ent->name_len] = '\0'; if (!strcmp(dname, name)) { free(dname); direntry = d_ent; break; } free(dname); dir_offset += d_ent->rec_len; } if (!direntry) { /* * We could not find the requested entry in this directory. */ fprintf(stderr, "Failed to locate %s!\n", name); return NULL; } else { return ext2_get_inode(direntry->inode); } }
/* * List all dirents */ void ls1( struct ext2_filesystem *fs, char *path ) { struct ext2_dir_entry_2 *dir = ext2_get_dirent_from_path( fs, path, "." ); if (!dir) { printf("ls: %s: No such file or directory\n",path); return; } struct ext2_inode *dirInode = ext2_get_inode( fs, dir->inode ); if (!dirInode) { printf("ls: %d: No such inode\n", dir->inode); return; } struct ext2_dir_entry_2 *firstDirent = ext2_get_first_dirent( fs, dirInode ); struct ext2_dir_entry_2 *currDirent = firstDirent; while ( currDirent->inode && ( currDirent - firstDirent < dirInode->i_size ) ) { printf( "%s\n", currDirent->name ); currDirent = ext2_get_next_dirent( fs, currDirent ); } }
ext2_DIR* ext2_opendir(ext2_VOLUME *volume, const char *name) { ext2_DIR* dir; int ino; struct ext2_inode *inode; int ret; ino = ext2_seek_name(volume, name); if (ino == 0) return NULL; inode = (struct ext2_inode*)malloc(sizeof(struct ext2_inode)); if (inode == NULL) return NULL; ret = ext2_get_inode(volume, ino, inode); if (ret == -1) { free(inode); return NULL; } if (!S_ISDIR(inode->i_mode)) { free(inode); return NULL; } dir = (ext2_DIR*)malloc(sizeof(ext2_DIR)); if (dir == NULL) { free(inode); return NULL; } dir->volume = (ext2_VOLUME*)volume; dir->inode = inode; dir->index = 0; return dir; }
int ext2(void) { printf("Hello World, this is the Ext2 FS\n"); // Hardcode test fs into memory so that we can test read // Set up the superblock struct ext2_super_block *sb; sb = (struct ext2_super_block*) (VIRT_MEM_LOCATION + EXT2_SUPERBLOCK_LOCATION); sb->s_inodes_count = 50; sb->s_blocks_count = 8192; sb->s_r_blocks_count = 6; sb->s_free_blocks_count = 8186; sb->s_free_inodes_count = 49; sb->s_first_data_block = 1; sb->s_log_block_size = 0; sb->s_log_frag_size = 0; sb->s_blocks_per_group = 8192; sb->s_frags_per_group = 8192; sb->s_inodes_per_group = 50; sb->s_magic = EXT2_MAGIC; sb->s_state = EXT2_VALID_FS; sb->s_errors = EXT2_ERRORS_CONTINUE; sb->s_creator_os = EXT2_OS_XINU; sb->s_first_ino = 2; sb->s_inode_size = sizeof( struct ext2_inode ); sb->s_block_group_nr = 0; char name[16] = "FAKE RAM FS :D"; memcpy(sb->s_volume_name,name,16); // Set up the group descriptors table struct ext2_group_desc *gpd; // DUMB POINTER ARITHMATIC gpd = (struct ext2_group_desc *) (sb + 1); gpd->bg_block_bitmap = 2; gpd->bg_inode_bitmap = 3; gpd->bg_inode_table = 4; gpd->bg_free_blocks_count = 44; gpd->bg_free_inodes_count = 19; gpd->bg_used_dirs_count = 1; // Set up the block bitmap uint8 *blBitmap; blBitmap = (uint8 *) (sb + 2); blBitmap[0] = 0x3F; // super block int i; for (i = 6; i < sb->s_blocks_count; i++) blBitmap[i] = 0; // Set up the inode bitmap uint8 *iBitmap; iBitmap = (uint8 *) (sb + 3); iBitmap[0] = 0x1; // . for (i = 1; i < sb->s_inodes_count; i++) iBitmap[i] = 0; // Set up the inode table struct ext2_inode *iTbl; iTbl = (struct ext2_inode *) (sb + 4); // Set up . inode iTbl->i_mode = EXT2_S_IFDIR; iTbl->i_size = sizeof(struct ext2_dir_entry_2); iTbl->i_links_count = 0; iTbl->i_blocks = 1; iTbl->i_flags = EXT2_NODUMP_FL; iTbl->i_block[0] = 5; // Set up . entry for the home directory struct ext2_dir_entry_2 *blk5; blk5 = (struct ext2_dir_entry_2 *) (sb + 5); blk5->inode = 1; blk5->next_dirent = 0; blk5->name_len = 1; blk5->filetype = 2; char homeName[255] = "."; memcpy(blk5->name, homeName, 255); _fs_ext2_init(); touch1( xinu_fs, "./", "test" ); char bufferL[9] = "Go long!"; uint32 bytes_written; ext2_write_status stat = ext2_write_file_by_path( xinu_fs, "./test", bufferL, &bytes_written, 0, 8 ); touch1( xinu_fs, "./", "yo"); stat = ext2_write_file_by_path( xinu_fs, "./yo", bufferL, &bytes_written, 0, 8 ); touch1( xinu_fs, "./", "whoah" ); stat = ext2_write_file_by_path( xinu_fs, "./whoah", bufferL, &bytes_written, 0, 8 ); touch1( xinu_fs, "./", "iasjdf" ); stat = ext2_write_file_by_path( xinu_fs, "./iasjdf", bufferL, &bytes_written, 0, 8 ); touch1( xinu_fs, "./", "f" ); stat = ext2_write_file_by_path( xinu_fs, "./f", bufferL, &bytes_written, 0, 8 ); ls1( xinu_fs, "./" ); printf("removing yo\n"); rm1( xinu_fs, "./", "yo" ); ls1( xinu_fs, "./" ); printf("touching asdf\n"); touch1( xinu_fs, "./", "asdf" ); stat = ext2_write_file_by_path( xinu_fs, "./asdf", bufferL, &bytes_written, 0, 8 ); ls1( xinu_fs, "./" ); printf("mking dir\n"); mkdir1( xinu_fs, "./", "dir" ); ls1( xinu_fs, "./" ); printf("touching yo\n"); touch1( xinu_fs, "./dir/", "yo" ); ls1( xinu_fs, "./dir/"); copy1( xinu_fs, "./", "whoah", "./", "hello" ); ls1( xinu_fs, "./" ); cat1( xinu_fs, "./", "hello" ); copy1( xinu_fs, "./", "hello", "./dir/", "hello" ); printf("HERE\n"); ls1( xinu_fs, "./dir/" ); cat1( xinu_fs, "./dir/", "hello" ); printf("removeing\n"); mv1( xinu_fs, "./dir/", "yo", "./", "a" ); ls1( xinu_fs, "./" ); cat1( xinu_fs, "./", "a" ); #if 0 // Test the read/write functions printf("Testing hardcoded data\n"); print_superblock( xinu_fs->sb ); struct ext2_inode *i1 = ext2_get_inode(xinu_fs, 1); print_inode( i1, 1, xinu_fs ); struct ext2_dir_entry_2 *home = ext2_get_first_dirent(xinu_fs, i1 ); print_dirent( home ); uint32 inode_num = ext2_inode_alloc( xinu_fs ); struct ext2_inode *i2 = ext2_get_inode( xinu_fs, inode_num+1 ); i2->i_mode = EXT2_S_IFREG; i2->i_size = 0; printf("Allocated new inode\n"); print_inode( i2, inode_num+1, xinu_fs ); struct ext2_dir_entry_2 *dirent = ext2_dirent_alloc( xinu_fs, i1 ); dirent->inode = 2; dirent->next_dirent = 0; dirent->name_len = 4; dirent->filetype = EXT2_FT_REG_FILE; char testName[255] = "test"; memcpy(dirent->name, testName, 255); printf("Allocated new dir_entry_2 test\n"); print_dirent( dirent ); char path[8] = "./test"; char buffer[14] = "Writing! Yay!"; char bufferL[9] = "Go long!"; uint32 bytes_written; ext2_write_status stat = ext2_write_file_by_path( xinu_fs, path, buffer, &bytes_written, 0, 13 ); printf("bytes_written = %d stat = %d\n", bytes_written, stat); char buffer2[12*1024]; // stat = ext2_write_file_by_path( xinu_fs, path, buffer2, // &bytes_written, 13, (12*1024)-1 ); printf("bytes_written = %d stat = %d\n", bytes_written, stat); // stat = ext2_write_file_by_path( xinu_fs, path, bufferL, // &bytes_written, (12*1024)+12, 8 ); printf("bytes_written = %d stat = %d\n", bytes_written, stat); int read = 0; char readBuf[30]; read = ext2_read_dirent( xinu_fs, dirent, readBuf, 0, 29); printf("Read %d bytes readBuf = %s\n", read, readBuf); // read = ext2_read_dirent( xinu_fs, dirent, readBuf, (12*1024)+12, 10); // printf("Read %d bytes readBuf = %s\n", read, readBuf); #endif return 0; }
static int ext2_load_linux(int fd,int index, const unsigned char *path) { struct ext2_inode *ext2_raw_inode; ext2_dirent *de; unsigned char *bh; int i; unsigned int inode; int find = 1; unsigned char s[EXT2_NAME_LEN]; unsigned char pathname[EXT2_NAME_LEN], *pathnameptr; unsigned char *directoryname; int showdir, lookupdir; showdir = 0; lookupdir = 0; bh = 0; if(read_super_block(fd,index)) return -1; if((path[0]==0) || (path[strlen(path)-1] == '/')) lookupdir = 1; strncpy(pathname,path,sizeof(pathname)); pathnameptr = pathname; for(inode = EXT2_ROOT_INO; find; ) { for(i = 0; pathnameptr[i] && pathnameptr[i] != '/'; i++); pathnameptr[i] = 0; directoryname = (unsigned char *)pathnameptr; pathnameptr = (unsigned char *)(pathnameptr + i + 1); if(!strlen(directoryname) && lookupdir) showdir = 1; if(ext2_get_inode(fd, inode, &ext2_raw_inode)) { printf("load EXT2_ROOT_INO error"); return -1; } if(!bh) bh = (unsigned char *)malloc(sb_block_size + ext2_raw_inode->i_size); if(!bh) { printf("Error in allocting memory for file content!\n"); return -1; } if(ext2_read_file(fd, bh, ext2_raw_inode->i_size, 0, ext2_raw_inode) != ext2_raw_inode->i_size) return -1; de = (ext2_dirent *)bh; find = 0; for ( ; ((unsigned char *) de < bh + ext2_raw_inode->i_size) && (de->rec_len > 0) && (de->name_len > 0); de = ext2_next_entry(de)) { strncpy(s,de->name,de->name_len); s[de->name_len]='\0';//*(de->name+de->name_len)='\0'; #ifdef DEBUG_IDE printf("entry:name=%s,inode=%d,rec_len=%d,name_len=%d,file_type=%d\n",s,de->inode,de->rec_len,de->name_len,de->file_type); #endif if(showdir) printf("%s%s",s,((de->file_type)&2)?"/ ":" "); if (!ext2_entrycmp(directoryname, de->name, de->name_len)) { if(de->file_type == EXT2_FT_REG_FILE) { if (ext2_get_inode(fd, de->inode, &the_inode)) { printf("load EXT2_ROOT_INO error"); free(bh); return -1; } free(bh); return 0; } find = 1; inode = de->inode; break; } } if(!find) { free(bh); if(!lookupdir) printf("Not find the file or directory!\n"); else printf("\n"); return -1; } } return -1; }
struct directory *dir_lookup(struct block *d, const char *path){ char *path_copy, *token, *save_ptr; struct directory *cur,*next,*last,*file_ptr; struct directory *found = NULL; ASSERT(path != NULL); // copy path path_copy = kmalloc(strlen(path)+1); memcpy(path_copy,path,strlen(path)+1); // start from root last = NULL; cur = dir_get_root(d); ASSERT(cur != NULL); // search path for(token = strtok_r(path_copy,"/",&save_ptr); token != NULL; token = strtok_r(NULL,"/",&save_ptr)){ // check if current directory is the same as the last if(cur == last) { file_ptr = NULL; break; } // look up current directory file_ptr = dir_lookup_current(cur,token); last = cur; //save current directory // if file is directory if(file_ptr != NULL && file_ptr->inode != 0 && file_ptr->file_type == EXT2_FT_DIR){ // get file inode, it is temporary struct inode *file_ino = ext2_get_inode(d,file_ptr->inode); if(file_ino == NULL || (file_ino->i_mode & EXT2_S_IFDIR) == 0){ file_ptr = NULL; if(file_ino != NULL) kfree(file_ino); break; } // read directory file next = kmalloc(file_ino->i_size); if(next == NULL) { file_ptr = NULL; kfree(file_ino); break; } inode_read_at(d,file_ino,next,file_ino->i_size,0); // free temporary memory and switch directory kfree(file_ino); kfree(cur); cur = next; } } // file found if(file_ptr != NULL && file_ptr->inode != 0){ found = kmalloc(sizeof(struct directory)); memcpy(found,file_ptr,sizeof(struct directory)); } kfree(cur); kfree(path_copy); return found; }