示例#1
0
文件: ext2_disk.c 项目: descent/osdev
/**
 * Return the 'index'th directory entry in the directory represented by 'inode'.
 * Caller should free the memory.
 */
ext2_dir_t *ext2_disk_direntry(ext2_inodetable_t *inode, uint32_t no, uint32_t index) {
	uint8_t *block = malloc(BLOCKSIZE);
	uint8_t block_nr = 0;
	ext2_disk_inode_read_block(inode, no, block_nr, block);
	uint32_t dir_offset = 0;
	uint32_t total_offset = 0;
	uint32_t dir_index = 0;
	
	while (total_offset < inode->size && dir_index <= index) {
		ext2_dir_t *d_ent = (ext2_dir_t *)((uintptr_t)block + dir_offset);
	
		if (dir_index == index) {
			ext2_dir_t *out = malloc(d_ent->rec_len);
			memcpy(out, d_ent, d_ent->rec_len);
			free(block);
			return out;
		}

		dir_offset += d_ent->rec_len;
		total_offset += d_ent->rec_len;
		dir_index++;

		// move on to the next block of this directory if needed.
		if (dir_offset >= BLOCKSIZE) {
			block_nr++;
			dir_offset -= BLOCKSIZE;
			ext2_disk_inode_read_block(inode, no, block_nr, block);
		}
	}
	
	free(block);
	return NULL;
}
示例#2
0
文件: ext2_disk.c 项目: campaul/osdev
uint32_t write_ext2_disk(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
	ext2_inodetable_t *inode = ext2_disk_inode(node->inode);
	uint32_t end = offset + size;
	uint32_t start_block 	= offset / BLOCKSIZE;
	uint32_t end_block		= end / BLOCKSIZE;
	uint32_t end_size		= end - end_block * BLOCKSIZE;
	uint32_t size_to_write  = end - offset;
	kprintf("[kernel/ext2] Write at node 0x%x, offset %d, size %d, buffer=0x%x\n", node, offset, size, buffer);
	if (end_size == 0) {
		end_block--;
	}
	
	// need to update if size has increased.
	if (inode->size < end) {
		inode->size = end;
		ext2_disk_write_inode(inode, node->inode);
	}
	
	if (start_block == end_block) {
		void *buf = malloc(BLOCKSIZE);
		ext2_disk_inode_read_block(inode, node->inode, start_block, buf);
		memcpy((uint8_t *)((uintptr_t)buf + (offset % BLOCKSIZE)), buffer, size_to_write);
		kprintf("[kernel/ext2] Single-block write.\n");
		ext2_disk_inode_write_block(inode, node->inode, start_block, buf);
		free(buf);
		free(inode);
		return size_to_write;
	} else {
		uint32_t block_offset;
		uint32_t blocks_read = 0;
		for (block_offset = start_block; block_offset < end_block; block_offset++, blocks_read++) {
			if (block_offset == start_block) {
				void *buf = malloc(BLOCKSIZE);
				ext2_disk_inode_read_block(inode, node->inode, block_offset, buf);
				memcpy((uint8_t *)((uint32_t)buf + (offset % BLOCKSIZE)), buffer, BLOCKSIZE - (offset % BLOCKSIZE));
				kprintf("[kernel/ext2] Writing block [loop...]...\n");
				ext2_disk_inode_write_block(inode, node->inode, start_block, buf);
				free(buf);
			} else {
				kprintf("[kernel/ext2] Writing block [buffer...?]...\n");
				ext2_disk_inode_write_block(inode, node->inode, block_offset, 
						buffer + BLOCKSIZE * blocks_read - (block_offset % BLOCKSIZE));
			}
		}
		void *buf = malloc(BLOCKSIZE);
		ext2_disk_inode_read_block(inode, node->inode, end_block, buf);
		memcpy(buf, buffer + BLOCKSIZE * blocks_read - (block_offset % BLOCKSIZE), end_size);
		kprintf("[kernel/ext2] Writing block [tail]...\n");
		ext2_disk_inode_write_block(inode, node->inode, end_block, buf);
		free(buf);
	}
	free(inode);
	return size_to_write;
}
示例#3
0
文件: ext2_disk.c 项目: descent/osdev
uint32_t read_ext2_disk(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
	ext2_inodetable_t *inode = ext2_disk_inode(node->inode);
	uint32_t end;
	if (offset + size > inode->size) {
		end = inode->size;
	} else {
		end = offset + size;
	}
	uint32_t start_block  = offset / BLOCKSIZE;
	uint32_t end_block    = end / BLOCKSIZE;
	uint32_t end_size     = end - end_block * BLOCKSIZE;
	uint32_t size_to_read = end - offset;
	if (end_size == 0) {
		end_block--;
	}
	if (start_block == end_block) {
		void *buf = malloc(BLOCKSIZE);
		ext2_disk_inode_read_block(inode, node->inode, start_block, buf);
		memcpy(buffer, (uint8_t *)(((uint32_t)buf) + (offset % BLOCKSIZE)), size_to_read);
		free(buf);
		free(inode);
		return size_to_read;
	} else {
		uint32_t block_offset;
		uint32_t blocks_read = 0;
		for (block_offset = start_block; block_offset < end_block; block_offset++, blocks_read++) {
			if (block_offset == start_block) {
				void *buf = malloc(BLOCKSIZE);
				ext2_disk_inode_read_block(inode, node->inode, block_offset, buf);
				memcpy(buffer, (uint8_t *)(((uint32_t)buf) + (offset % BLOCKSIZE)), BLOCKSIZE - (offset % BLOCKSIZE));
				free(buf);
			} else {
				void *buf = malloc(BLOCKSIZE);
				ext2_disk_inode_read_block(inode, node->inode, block_offset, buf);
				memcpy(buffer + BLOCKSIZE * blocks_read - (offset % BLOCKSIZE), buf, BLOCKSIZE);
				free(buf);
			}
		}
		void *buf = malloc(BLOCKSIZE);
		ext2_disk_inode_read_block(inode, node->inode, end_block, buf);
		memcpy(buffer + BLOCKSIZE * blocks_read - (offset % BLOCKSIZE), buf, end_size);
		free(buf);
	}
	free(inode);
	return size_to_read;
}
示例#4
0
文件: ext2_disk.c 项目: descent/osdev
/**
 * Find the actual inode in the ramdisk image for the requested file.
 */
fs_node_t *finddir_ext2_disk(fs_node_t *node, char *name) {
	
	ext2_inodetable_t *inode = ext2_disk_inode(node->inode);
	assert(inode->mode & EXT2_S_IFDIR);
	void *block = malloc(BLOCKSIZE);
	ext2_dir_t *direntry = NULL;
	uint8_t block_nr = 0;
	ext2_disk_inode_read_block(inode, node->inode, block_nr, block);
	uint32_t dir_offset = 0;
	uint32_t total_offset = 0;

	// Look through the requested entries until we find what we're looking for
#if EXT2_DEBUG_BLOCK_DESCRIPTORS
	kprintf("file looking for: %s\n", name);
	kprintf("total size: %d\n", inode->size);
#endif
	while (total_offset < inode->size) {
#if EXT2_DEBUG_BLOCK_DESCRIPTORS
		kprintf("dir_offset: %d\n", dir_offset);
		kprintf("total_offset: %d\n", total_offset);
#endif
		ext2_dir_t *d_ent = (ext2_dir_t *)((uintptr_t)block + dir_offset);
		
		if (strlen(name) != d_ent->name_len) {
			dir_offset += d_ent->rec_len;
			total_offset += d_ent->rec_len;

			// move on to the next block of this directory if need.
			if (dir_offset >= BLOCKSIZE) {
				block_nr++;
				dir_offset -= BLOCKSIZE;
				ext2_disk_inode_read_block(inode, node->inode, block_nr, block);
			}

			continue;
		}

		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 EXT2_DEBUG_BLOCK_DESCRIPTORS
		kprintf("cur file: %s\n", dname);
#endif
		if (!strcmp(dname, name)) {
			free(dname);
			direntry = malloc(d_ent->rec_len);
			memcpy(direntry, d_ent, d_ent->rec_len);
			break;
		}
		free(dname);

		dir_offset += d_ent->rec_len;
		total_offset += d_ent->rec_len;

		// move on to the next block of this directory if need.
		if (dir_offset >= BLOCKSIZE) {
			block_nr++;
			dir_offset -= BLOCKSIZE;
			ext2_disk_inode_read_block(inode, node->inode, block_nr, block);
		}
	}
	free(inode);
	free(block);
	if (!direntry) {
		// We could not find the requested entry in this directory.
		return NULL;
	}
	fs_node_t *outnode = malloc(sizeof(fs_node_t));
	inode = ext2_disk_inode(direntry->inode);
	ext2_disk_node_from_file(inode, direntry, outnode);
	free(inode);
	return outnode;
}
示例#5
0
文件: ext2_disk.c 项目: descent/osdev
/**
 * Insert an entry named 'name' with type 'type' into a directory 'p_node' 
 * at the end.
 * This function assumes that parent directory 'p_node' does not contain
 * any entry with same name as 'name'. Caller should ensure this.
 */
void insertdir_ext2_disk(ext2_inodetable_t *p_node, uint32_t no, uint32_t inode, char *name, uint8_t type) {
	/* XXX HACK This needs to be seriously fixed up. */
	kprintf("[kernel/ext2] Request to insert new directory entry at 0x%x#%d->%d '%s' type %d\n", p_node, no, inode, name, type);
	assert(p_node->mode & EXT2_S_IFDIR);
	void *block = malloc(BLOCKSIZE);
	uint32_t block_nr = 0;
	ext2_disk_inode_read_block(p_node, no, block_nr, block);
	uint32_t dir_offset = 0;
	uint32_t total_offset = 0;

	// first, iterate pass the last entry in the parent directory.
	while (total_offset < p_node->size) {
		ext2_dir_t *d_ent = (ext2_dir_t *)((uintptr_t)block + dir_offset);
		if (d_ent->rec_len + total_offset == p_node->size) {
			d_ent->rec_len = d_ent->name_len + sizeof(ext2_dir_t);
			while (d_ent->rec_len % 4 > 0) {
				d_ent->rec_len++;
			}
			dir_offset   += d_ent->rec_len;
			total_offset += d_ent->rec_len;
			break;
		}

		dir_offset += d_ent->rec_len;
		total_offset += d_ent->rec_len;

		// move on to the next block of this directory if needed.
		if (dir_offset >= BLOCKSIZE) {
			block_nr++;
			dir_offset -= BLOCKSIZE;
			ext2_disk_inode_read_block(p_node, no, block_nr, block);
			kprintf("[kernel/ext2] Advancing to next block...\n");
		}
	}

	kprintf("[kernel/ext2] Total Offset = %d; block = %d; offset within block = %d\n", total_offset, block_nr, dir_offset);

	// Put the new directory entry at 'dir_offset' in block 'block_nr'.
	uint32_t size = p_node->size - total_offset;
	if (dir_offset + size > BLOCKSIZE) {
		kprintf("\033[1;31m[kernel/ext2] Just a warning: You probably just f****d everything.\033[0m\n");
	}
	ext2_dir_t *new_entry = malloc(size);

	// Initialize the new entry.
	new_entry->inode = inode;
	new_entry->rec_len = size;
	new_entry->name_len = (uint8_t)strlen(name);
	new_entry->file_type = type;
	memcpy(&new_entry->name, name, strlen(name));

	// Write back to block.
	memcpy(((uint8_t *)block) + dir_offset, new_entry, size);
	memset(((uint8_t *)block) + dir_offset + new_entry->rec_len, 0x00, 4);
	ext2_disk_inode_write_block(p_node, no, block_nr, block);

	// Update parent node size
	//p_node->size += size;
	ext2_disk_write_inode(p_node, no);

	free(block);
}
示例#6
0
文件: ext2_disk.c 项目: campaul/osdev
/**
 * Insert an entry named 'name' with type 'type' into a directory 'p_node' 
 * at the end.
 * This function assumes that parent directory 'p_node' does not contain
 * any entry with same name as 'name'. Caller should ensure this.
 */
void insertdir_ext2_disk(ext2_inodetable_t *p_node, uint32_t no, uint32_t inode, char *name, uint8_t type) {
	/* XXX HACK This needs to be seriously fixed up. */
	debug_print(NOTICE, "Request to insert new directory entry at 0x%x#%d->%d '%s' type %d", p_node, no, inode, name, type);
	assert(p_node->mode & EXT2_S_IFDIR);
	void *block = malloc(BLOCKSIZE);
	uint32_t block_nr = 0;
	ext2_disk_inode_read_block(p_node, no, block_nr, block);
	uint32_t dir_offset = 0;
	uint32_t total_offset = 0;

	// first, iterate pass the last entry in the parent directory.
	while (total_offset < p_node->size) {
		ext2_dir_t *d_ent = (ext2_dir_t *)((uintptr_t)block + dir_offset);
		if (d_ent->rec_len + total_offset == p_node->size) {
			d_ent->rec_len = d_ent->name_len + sizeof(ext2_dir_t);
			while (d_ent->rec_len % 4 > 0) {
				d_ent->rec_len++;
			}
			dir_offset   += d_ent->rec_len;
			total_offset += d_ent->rec_len;
			break;
		}

		dir_offset += d_ent->rec_len;
		total_offset += d_ent->rec_len;

		// move on to the next block of this directory if needed.
		if (dir_offset >= BLOCKSIZE) {
			block_nr++;
			dir_offset -= BLOCKSIZE;
			ext2_disk_inode_read_block(p_node, no, block_nr, block);
			debug_print(NOTICE, "Advancing to next block...");
		}
	}

	debug_print(NOTICE, "total offset = %d; block = %d; offset within block = %d", total_offset, block_nr, dir_offset);

	// Put the new directory entry at 'dir_offset' in block 'block_nr'.
	uint32_t size = p_node->size - total_offset;
	if (dir_offset + size > BLOCKSIZE) {
		debug_print(WARNING, "Directory entry is beyond first block of directory. This might be bad.");
	}
	ext2_dir_t *new_entry = malloc(size);

	// Initialize the new entry.
	new_entry->inode = inode;
	new_entry->rec_len = size;
	new_entry->name_len = (uint8_t)strlen(name);
	new_entry->file_type = type;
	memcpy(&new_entry->name, name, strlen(name));

	// Write back to block.
	memcpy(((uint8_t *)block) + dir_offset, new_entry, size);
	memset(((uint8_t *)block) + dir_offset + new_entry->rec_len, 0x00, 4);
	ext2_disk_inode_write_block(p_node, no, block_nr, block);

	free(new_entry);

	// Update parent node size
	//p_node->size += size;
	ext2_disk_write_inode(p_node, no);

	free(block);
}