--- zzzz-none-000/linux-2.4.17/fs/jffs2/read.c 2001-09-14 21:04:07.000000000 +0000 +++ sangam-fb-322/linux-2.4.17/fs/jffs2/read.c 2004-11-24 13:22:18.000000000 +0000 @@ -1,7 +1,7 @@ /* * JFFS2 -- Journalling Flash File System, Version 2. * - * Copyright (C) 2001 Red Hat, Inc. + * Copyright (C) 2001, 2002 Red Hat, Inc. * * Created by David Woodhouse * @@ -31,14 +31,14 @@ * provisions above, a recipient may use your version of this file * under either the RHEPL or the GPL. * - * $Id: read.c,v 1.13 2001/05/01 16:24:44 dwmw2 Exp $ + * $Id: read.c,v 1.1.1.1 2003/06/23 22:18:37 jharrell Exp $ * */ #include #include -#include #include +#include #include "nodelist.h" #include "crc32.h" @@ -46,7 +46,7 @@ { struct jffs2_raw_inode *ri; size_t readlen; - __u32 crc; + uint32_t crc; unsigned char *decomprbuf = NULL; unsigned char *readbuf = NULL; int ret = 0; @@ -55,7 +55,7 @@ if (!ri) return -ENOMEM; - ret = c->mtd->read(c->mtd, fd->raw->flash_offset & ~3, sizeof(*ri), &readlen, (char *)ri); + ret = jffs2_flash_read(c, fd->raw->flash_offset & ~3, sizeof(*ri), &readlen, (char *)ri); if (ret) { jffs2_free_raw_inode(ri); printk(KERN_WARNING "Error reading node from 0x%08x: %d\n", fd->raw->flash_offset & ~3, ret); @@ -118,7 +118,7 @@ } D2(printk(KERN_DEBUG "Read %d bytes to %p\n", ri->csize, readbuf)); - ret = c->mtd->read(c->mtd, (fd->raw->flash_offset &~3) + sizeof(*ri), ri->csize, &readlen, readbuf); + ret = jffs2_flash_read(c, (fd->raw->flash_offset &~3) + sizeof(*ri), ri->csize, &readlen, readbuf); if (!ret && readlen != ri->csize) ret = -EIO; @@ -155,3 +155,99 @@ return ret; } + +int jffs2_read_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, + unsigned char *buf, uint32_t offset, uint32_t len) +{ + uint32_t end = offset + len; + struct jffs2_node_frag *frag = f->fraglist; + int ret; + + D1(printk(KERN_DEBUG "jffs2_read_inode_range: ino #%u, range 0x%08x-0x%08x\n", + f->inocache->ino, offset, offset+len)); + + while(frag && frag->ofs + frag->size <= offset) { + D2(printk(KERN_DEBUG "skipping frag %d-%d; before the region we care about\n", frag->ofs, frag->ofs + frag->size)); + frag = frag->next; + } + /* XXX FIXME: Where a single physical node actually shows up in two + frags, we read it twice. Don't do that. */ + /* Now we're pointing at the first frag which overlaps our page */ + while(offset < end) { + D2(printk(KERN_DEBUG "jffs2_read_inode_range: offset %d, end %d\n", offset, end)); + if (!frag || frag->ofs > offset) { + uint32_t holesize = end - offset; + if (frag) { + D1(printk(KERN_NOTICE "Eep. Hole in ino #%u fraglist. frag->ofs = 0x%08x, offset = 0x%08x\n", f->inocache->ino, frag->ofs, offset)); + holesize = min(holesize, frag->ofs - offset); + D1(jffs2_print_frag_list(f)); + } + D1(printk(KERN_DEBUG "Filling non-frag hole from %d-%d\n", offset, offset+holesize)); + memset(buf, 0, holesize); + buf += holesize; + offset += holesize; + continue; + } else if (frag->ofs < offset && (offset & (PAGE_CACHE_SIZE-1)) != 0) { + D1(printk(KERN_NOTICE "Eep. Overlap in ino #%u fraglist. frag->ofs = 0x%08x, offset = 0x%08x\n", + f->inocache->ino, frag->ofs, offset)); + D1(jffs2_print_frag_list(f)); + memset(buf, 0, end - offset); + return -EIO; + } else if (!frag->node) { + uint32_t holeend = min(end, frag->ofs + frag->size); + D1(printk(KERN_DEBUG "Filling frag hole from %d-%d (frag 0x%x 0x%x)\n", offset, holeend, frag->ofs, frag->ofs + frag->size)); + memset(buf, 0, holeend - offset); + buf += holeend - offset; + offset = holeend; + frag = frag->next; + continue; + } else { + uint32_t readlen; + readlen = min(frag->size, end - offset); + D1(printk(KERN_DEBUG "Reading %d-%d from node at 0x%x\n", frag->ofs, frag->ofs+readlen, frag->node->raw->flash_offset & ~3)); + ret = jffs2_read_dnode(c, frag->node, buf, frag->ofs - frag->node->ofs, readlen); + D2(printk(KERN_DEBUG "node read done\n")); + if (ret) { + D1(printk(KERN_DEBUG"jffs2_read_inode_range error %d\n",ret)); + memset(buf, 0, frag->size); + return ret; + } + } + buf += frag->size; + offset += frag->size; + frag = frag->next; + D2(printk(KERN_DEBUG "node read was OK. Looping\n")); + } + return 0; +} + +/* Core function to read symlink target. */ +char *jffs2_getlink(struct jffs2_sb_info *c, struct jffs2_inode_info *f) +{ + char *buf; + int ret; + + down(&f->sem); + + if (!f->metadata) { + printk(KERN_NOTICE "No metadata for symlink inode #%u\n", f->inocache->ino); + up(&f->sem); + return ERR_PTR(-EINVAL); + } + buf = kmalloc(f->metadata->size+1, GFP_USER); + if (!buf) { + up(&f->sem); + return ERR_PTR(-ENOMEM); + } + buf[f->metadata->size]=0; + + ret = jffs2_read_dnode(c, f->metadata, buf, 0, f->metadata->size); + + up(&f->sem); + + if (ret) { + kfree(buf); + return ERR_PTR(ret); + } + return buf; +}