 6c46a77d95
			
		
	
	
		6c46a77d95
		
	
	
	
	
		
			
			- The lmfs_get_block*(3) API calls may now return an error. The idea is to encourage a next generation of file system services to do a better job at dealing with block read errors than the MFS-derived implementations do. These existing file systems have been changed to panic immediately upon getting a block read error, in order to let unchecked errors cause corruption. Note that libbdev already retries failing I/O operations a few times first. - The libminixfs block device I/O module (bio.c) now deals properly with end-of-file conditions on block devices. Since a device or partition size may not be a multiple of the root file system's block size, support for partial block retrival has been added, with a new internal lmfs_get_partial_block(3) call. A new test program, test85, tests the new handling of EOF conditions when reading, writing, and memory-mapping a block device. Change-Id: I05e35b6b8851488328a2679da635ebba0c6d08ce
		
			
				
	
	
		
			97 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			97 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include "inc.h"
 | |
| 
 | |
| static struct dir_extent dir_extents[NR_DIR_EXTENT_RECORDS];
 | |
| 
 | |
| struct dir_extent* alloc_extent(void)
 | |
| {
 | |
| 	/* Return a free extent from the pool. */
 | |
| 	int i;
 | |
| 	struct dir_extent *extent;
 | |
| 
 | |
| 	for (i = 0; i < NR_DIR_EXTENT_RECORDS; i++) {
 | |
| 		extent = &dir_extents[i];
 | |
| 
 | |
| 		if (extent->in_use == 0) {
 | |
| 			memset(extent, 0, sizeof(*extent));
 | |
| 			extent->in_use = 1;
 | |
| 
 | |
| 			return extent;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	panic("No free extents in cache");
 | |
| }
 | |
| 
 | |
| void free_extent(struct dir_extent *e)
 | |
| {
 | |
| 	if (e == NULL)
 | |
| 		return;
 | |
| 
 | |
| 	if (e->in_use == 0)
 | |
| 		panic("Trying to free unused extent");
 | |
| 
 | |
| 	free_extent(e->next);
 | |
| 	e->in_use = 0;
 | |
| }
 | |
| 
 | |
| struct buf* read_extent_block(struct dir_extent *e, size_t block)
 | |
| {
 | |
| 	struct buf *bp;
 | |
| 	size_t block_id;
 | |
| 	int r;
 | |
| 
 | |
| 	block_id = get_extent_absolute_block_id(e, block);
 | |
| 
 | |
| 	if (block_id == 0 || block_id >= v_pri.volume_space_size_l)
 | |
| 		return NULL;
 | |
| 
 | |
| 	/* Not all callers deal well with failure, so panic on I/O error. */
 | |
| 	if ((r = lmfs_get_block(&bp, fs_dev, block_id, NORMAL)) != OK)
 | |
| 		panic("ISOFS: error getting block (%llu,%zu): %d",
 | |
| 		    fs_dev, block_id, r);
 | |
| 
 | |
| 	return bp;
 | |
| }
 | |
| 
 | |
| size_t get_extent_absolute_block_id(struct dir_extent *e, size_t block)
 | |
| {
 | |
| 	size_t extent_offset = 0;
 | |
| 
 | |
| 	if (e == NULL)
 | |
| 		return 0;
 | |
| 
 | |
| 	/* Retrieve the extent on which the block lies. */
 | |
| 	while(block > extent_offset + e->length) {
 | |
| 		if (e->next == NULL)
 | |
| 			return 0;
 | |
| 
 | |
| 		extent_offset += e->length;
 | |
| 		e = e->next;
 | |
| 	}
 | |
| 
 | |
| 	return e->location + block - extent_offset;
 | |
| }
 | |
| 
 | |
| time_t date7_to_time_t(const u8_t *date)
 | |
| {
 | |
| 	/* This function converts from the ISO 9660 7-byte time format to a
 | |
| 	 * time_t.
 | |
| 	 */
 | |
| 	struct tm ltime;
 | |
| 	signed char time_zone = (signed char)date[6];
 | |
| 
 | |
| 	ltime.tm_year = date[0];
 | |
| 	ltime.tm_mon = date[1] - 1;
 | |
| 	ltime.tm_mday = date[2];
 | |
| 	ltime.tm_hour = date[3];
 | |
| 	ltime.tm_min = date[4];
 | |
| 	ltime.tm_sec = date[5];
 | |
| 	ltime.tm_isdst = 0;
 | |
| 
 | |
| 	/* Offset from Greenwich Mean Time */
 | |
| 	if (time_zone >= -52 && time_zone <= 52)
 | |
| 		ltime.tm_hour += time_zone;
 | |
| 
 | |
| 	return mktime(<ime);
 | |
| }
 |