mirror of
				https://xff.cz/git/u-boot/
				synced 2025-10-31 02:15:45 +01:00 
			
		
		
		
	UBIFS: Change ubifsload to not read beyond the requested size
Until now ubifsload pads the destination with 0 up to a multiple of UBIFS_BLOCK_SIZE (4KiB) while reading a file to memory. This patch changes this behaviour to only read to the requested length. This is either the file length or the length/size provided as parameter to the ubifsload command. Signed-off-by: Stefan Roese <sr@denx.de>
This commit is contained in:
		| @@ -3,7 +3,7 @@ | |||||||
|  * |  * | ||||||
|  * Copyright (C) 2006-2008 Nokia Corporation. |  * Copyright (C) 2006-2008 Nokia Corporation. | ||||||
|  * |  * | ||||||
|  * (C) Copyright 2008-2009 |  * (C) Copyright 2008-2010 | ||||||
|  * Stefan Roese, DENX Software Engineering, sr@denx.de. |  * Stefan Roese, DENX Software Engineering, sr@denx.de. | ||||||
|  * |  * | ||||||
|  * This program is free software; you can redistribute it and/or modify it |  * This program is free software; you can redistribute it and/or modify it | ||||||
| @@ -567,7 +567,8 @@ dump: | |||||||
| 	return -EINVAL; | 	return -EINVAL; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int do_readpage(struct ubifs_info *c, struct inode *inode, struct page *page) | static int do_readpage(struct ubifs_info *c, struct inode *inode, | ||||||
|  | 		       struct page *page, int last_block_size) | ||||||
| { | { | ||||||
| 	void *addr; | 	void *addr; | ||||||
| 	int err = 0, i; | 	int err = 0, i; | ||||||
| @@ -601,17 +602,54 @@ static int do_readpage(struct ubifs_info *c, struct inode *inode, struct page *p | |||||||
| 			err = -ENOENT; | 			err = -ENOENT; | ||||||
| 			memset(addr, 0, UBIFS_BLOCK_SIZE); | 			memset(addr, 0, UBIFS_BLOCK_SIZE); | ||||||
| 		} else { | 		} else { | ||||||
| 			ret = read_block(inode, addr, block, dn); | 			/* | ||||||
| 			if (ret) { | 			 * Reading last block? Make sure to not write beyond | ||||||
| 				err = ret; | 			 * the requested size in the destination buffer. | ||||||
| 				if (err != -ENOENT) | 			 */ | ||||||
| 					break; | 			if (((block + 1) == beyond) || last_block_size) { | ||||||
| 			} else if (block + 1 == beyond) { | 				void *buff; | ||||||
| 				int dlen = le32_to_cpu(dn->size); | 				int dlen; | ||||||
| 				int ilen = i_size & (UBIFS_BLOCK_SIZE - 1); |  | ||||||
|  |  | ||||||
| 				if (ilen && ilen < dlen) | 				/* | ||||||
| 					memset(addr + ilen, 0, dlen - ilen); | 				 * We need to buffer the data locally for the | ||||||
|  | 				 * last block. This is to not pad the | ||||||
|  | 				 * destination area to a multiple of | ||||||
|  | 				 * UBIFS_BLOCK_SIZE. | ||||||
|  | 				 */ | ||||||
|  | 				buff = malloc(UBIFS_BLOCK_SIZE); | ||||||
|  | 				if (!buff) { | ||||||
|  | 					printf("%s: Error, malloc fails!\n", | ||||||
|  | 					       __func__); | ||||||
|  | 					err = -ENOMEM; | ||||||
|  | 					break; | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				/* Read block-size into temp buffer */ | ||||||
|  | 				ret = read_block(inode, buff, block, dn); | ||||||
|  | 				if (ret) { | ||||||
|  | 					err = ret; | ||||||
|  | 					if (err != -ENOENT) { | ||||||
|  | 						free(buff); | ||||||
|  | 						break; | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  |  | ||||||
|  | 				if (last_block_size) | ||||||
|  | 					dlen = last_block_size; | ||||||
|  | 				else | ||||||
|  | 					dlen = le32_to_cpu(dn->size); | ||||||
|  |  | ||||||
|  | 				/* Now copy required size back to dest */ | ||||||
|  | 				memcpy(addr, buff, dlen); | ||||||
|  |  | ||||||
|  | 				free(buff); | ||||||
|  | 			} else { | ||||||
|  | 				ret = read_block(inode, addr, block, dn); | ||||||
|  | 				if (ret) { | ||||||
|  | 					err = ret; | ||||||
|  | 					if (err != -ENOENT) | ||||||
|  | 						break; | ||||||
|  | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		if (++i >= UBIFS_BLOCKS_PER_PAGE) | 		if (++i >= UBIFS_BLOCKS_PER_PAGE) | ||||||
| @@ -649,6 +687,7 @@ int ubifs_load(char *filename, u32 addr, u32 size) | |||||||
| 	int err = 0; | 	int err = 0; | ||||||
| 	int i; | 	int i; | ||||||
| 	int count; | 	int count; | ||||||
|  | 	int last_block_size = 0; | ||||||
|  |  | ||||||
| 	c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY); | 	c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READONLY); | ||||||
| 	/* ubifs_findfile will resolve symlinks, so we know that we get | 	/* ubifs_findfile will resolve symlinks, so we know that we get | ||||||
| @@ -684,7 +723,13 @@ int ubifs_load(char *filename, u32 addr, u32 size) | |||||||
| 	page.index = 0; | 	page.index = 0; | ||||||
| 	page.inode = inode; | 	page.inode = inode; | ||||||
| 	for (i = 0; i < count; i++) { | 	for (i = 0; i < count; i++) { | ||||||
| 		err = do_readpage(c, inode, &page); | 		/* | ||||||
|  | 		 * Make sure to not read beyond the requested size | ||||||
|  | 		 */ | ||||||
|  | 		if (((i + 1) == count) && (size < inode->i_size)) | ||||||
|  | 			last_block_size = size - (i * PAGE_SIZE); | ||||||
|  |  | ||||||
|  | 		err = do_readpage(c, inode, &page, last_block_size); | ||||||
| 		if (err) | 		if (err) | ||||||
| 			break; | 			break; | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user