Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * JFFS2 -- Journalling Flash File System, Version 2.
0003  *
0004  * Copyright © 2001-2007 Red Hat, Inc.
0005  *
0006  * Created by David Woodhouse <dwmw2@infradead.org>
0007  *
0008  * For licensing information, see the file 'LICENCE' in this directory.
0009  *
0010  */
0011 
0012 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0013 
0014 #include <linux/kernel.h>
0015 #include <linux/slab.h>
0016 #include <linux/crc32.h>
0017 #include <linux/pagemap.h>
0018 #include <linux/mtd/mtd.h>
0019 #include <linux/compiler.h>
0020 #include "nodelist.h"
0021 #include "compr.h"
0022 
0023 int jffs2_read_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
0024              struct jffs2_full_dnode *fd, unsigned char *buf,
0025              int ofs, int len)
0026 {
0027     struct jffs2_raw_inode *ri;
0028     size_t readlen;
0029     uint32_t crc;
0030     unsigned char *decomprbuf = NULL;
0031     unsigned char *readbuf = NULL;
0032     int ret = 0;
0033 
0034     ri = jffs2_alloc_raw_inode();
0035     if (!ri)
0036         return -ENOMEM;
0037 
0038     ret = jffs2_flash_read(c, ref_offset(fd->raw), sizeof(*ri), &readlen, (char *)ri);
0039     if (ret) {
0040         jffs2_free_raw_inode(ri);
0041         pr_warn("Error reading node from 0x%08x: %d\n",
0042             ref_offset(fd->raw), ret);
0043         return ret;
0044     }
0045     if (readlen != sizeof(*ri)) {
0046         jffs2_free_raw_inode(ri);
0047         pr_warn("Short read from 0x%08x: wanted 0x%zx bytes, got 0x%zx\n",
0048             ref_offset(fd->raw), sizeof(*ri), readlen);
0049         return -EIO;
0050     }
0051     crc = crc32(0, ri, sizeof(*ri)-8);
0052 
0053     jffs2_dbg(1, "Node read from %08x: node_crc %08x, calculated CRC %08x. dsize %x, csize %x, offset %x, buf %p\n",
0054           ref_offset(fd->raw), je32_to_cpu(ri->node_crc),
0055           crc, je32_to_cpu(ri->dsize), je32_to_cpu(ri->csize),
0056           je32_to_cpu(ri->offset), buf);
0057     if (crc != je32_to_cpu(ri->node_crc)) {
0058         pr_warn("Node CRC %08x != calculated CRC %08x for node at %08x\n",
0059             je32_to_cpu(ri->node_crc), crc, ref_offset(fd->raw));
0060         ret = -EIO;
0061         goto out_ri;
0062     }
0063     /* There was a bug where we wrote hole nodes out with csize/dsize
0064        swapped. Deal with it */
0065     if (ri->compr == JFFS2_COMPR_ZERO && !je32_to_cpu(ri->dsize) &&
0066         je32_to_cpu(ri->csize)) {
0067         ri->dsize = ri->csize;
0068         ri->csize = cpu_to_je32(0);
0069     }
0070 
0071     D1(if(ofs + len > je32_to_cpu(ri->dsize)) {
0072             pr_warn("jffs2_read_dnode() asked for %d bytes at %d from %d-byte node\n",
0073                 len, ofs, je32_to_cpu(ri->dsize));
0074         ret = -EINVAL;
0075         goto out_ri;
0076     });
0077 
0078 
0079     if (ri->compr == JFFS2_COMPR_ZERO) {
0080         memset(buf, 0, len);
0081         goto out_ri;
0082     }
0083 
0084     /* Cases:
0085        Reading whole node and it's uncompressed - read directly to buffer provided, check CRC.
0086        Reading whole node and it's compressed - read into comprbuf, check CRC and decompress to buffer provided
0087        Reading partial node and it's uncompressed - read into readbuf, check CRC, and copy
0088        Reading partial node and it's compressed - read into readbuf, check checksum, decompress to decomprbuf and copy
0089     */
0090     if (ri->compr == JFFS2_COMPR_NONE && len == je32_to_cpu(ri->dsize)) {
0091         readbuf = buf;
0092     } else {
0093         readbuf = kmalloc(je32_to_cpu(ri->csize), GFP_KERNEL);
0094         if (!readbuf) {
0095             ret = -ENOMEM;
0096             goto out_ri;
0097         }
0098     }
0099     if (ri->compr != JFFS2_COMPR_NONE) {
0100         if (len < je32_to_cpu(ri->dsize)) {
0101             decomprbuf = kmalloc(je32_to_cpu(ri->dsize), GFP_KERNEL);
0102             if (!decomprbuf) {
0103                 ret = -ENOMEM;
0104                 goto out_readbuf;
0105             }
0106         } else {
0107             decomprbuf = buf;
0108         }
0109     } else {
0110         decomprbuf = readbuf;
0111     }
0112 
0113     jffs2_dbg(2, "Read %d bytes to %p\n", je32_to_cpu(ri->csize),
0114           readbuf);
0115     ret = jffs2_flash_read(c, (ref_offset(fd->raw)) + sizeof(*ri),
0116                    je32_to_cpu(ri->csize), &readlen, readbuf);
0117 
0118     if (!ret && readlen != je32_to_cpu(ri->csize))
0119         ret = -EIO;
0120     if (ret)
0121         goto out_decomprbuf;
0122 
0123     crc = crc32(0, readbuf, je32_to_cpu(ri->csize));
0124     if (crc != je32_to_cpu(ri->data_crc)) {
0125         pr_warn("Data CRC %08x != calculated CRC %08x for node at %08x\n",
0126             je32_to_cpu(ri->data_crc), crc, ref_offset(fd->raw));
0127         ret = -EIO;
0128         goto out_decomprbuf;
0129     }
0130     jffs2_dbg(2, "Data CRC matches calculated CRC %08x\n", crc);
0131     if (ri->compr != JFFS2_COMPR_NONE) {
0132         jffs2_dbg(2, "Decompress %d bytes from %p to %d bytes at %p\n",
0133               je32_to_cpu(ri->csize), readbuf,
0134               je32_to_cpu(ri->dsize), decomprbuf);
0135         ret = jffs2_decompress(c, f, ri->compr | (ri->usercompr << 8), readbuf, decomprbuf, je32_to_cpu(ri->csize), je32_to_cpu(ri->dsize));
0136         if (ret) {
0137             pr_warn("Error: jffs2_decompress returned %d\n", ret);
0138             goto out_decomprbuf;
0139         }
0140     }
0141 
0142     if (len < je32_to_cpu(ri->dsize)) {
0143         memcpy(buf, decomprbuf+ofs, len);
0144     }
0145  out_decomprbuf:
0146     if(decomprbuf != buf && decomprbuf != readbuf)
0147         kfree(decomprbuf);
0148  out_readbuf:
0149     if(readbuf != buf)
0150         kfree(readbuf);
0151  out_ri:
0152     jffs2_free_raw_inode(ri);
0153 
0154     return ret;
0155 }
0156 
0157 int jffs2_read_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
0158                unsigned char *buf, uint32_t offset, uint32_t len)
0159 {
0160     uint32_t end = offset + len;
0161     struct jffs2_node_frag *frag;
0162     int ret;
0163 
0164     jffs2_dbg(1, "%s(): ino #%u, range 0x%08x-0x%08x\n",
0165           __func__, f->inocache->ino, offset, offset + len);
0166 
0167     frag = jffs2_lookup_node_frag(&f->fragtree, offset);
0168 
0169     /* XXX FIXME: Where a single physical node actually shows up in two
0170        frags, we read it twice. Don't do that. */
0171     /* Now we're pointing at the first frag which overlaps our page
0172      * (or perhaps is before it, if we've been asked to read off the
0173      * end of the file). */
0174     while(offset < end) {
0175         jffs2_dbg(2, "%s(): offset %d, end %d\n",
0176               __func__, offset, end);
0177         if (unlikely(!frag || frag->ofs > offset ||
0178                  frag->ofs + frag->size <= offset)) {
0179             uint32_t holesize = end - offset;
0180             if (frag && frag->ofs > offset) {
0181                 jffs2_dbg(1, "Eep. Hole in ino #%u fraglist. frag->ofs = 0x%08x, offset = 0x%08x\n",
0182                       f->inocache->ino, frag->ofs, offset);
0183                 holesize = min(holesize, frag->ofs - offset);
0184             }
0185             jffs2_dbg(1, "Filling non-frag hole from %d-%d\n",
0186                   offset, offset + holesize);
0187             memset(buf, 0, holesize);
0188             buf += holesize;
0189             offset += holesize;
0190             continue;
0191         } else if (unlikely(!frag->node)) {
0192             uint32_t holeend = min(end, frag->ofs + frag->size);
0193             jffs2_dbg(1, "Filling frag hole from %d-%d (frag 0x%x 0x%x)\n",
0194                   offset, holeend, frag->ofs,
0195                   frag->ofs + frag->size);
0196             memset(buf, 0, holeend - offset);
0197             buf += holeend - offset;
0198             offset = holeend;
0199             frag = frag_next(frag);
0200             continue;
0201         } else {
0202             uint32_t readlen;
0203             uint32_t fragofs; /* offset within the frag to start reading */
0204 
0205             fragofs = offset - frag->ofs;
0206             readlen = min(frag->size - fragofs, end - offset);
0207             jffs2_dbg(1, "Reading %d-%d from node at 0x%08x (%d)\n",
0208                   frag->ofs+fragofs,
0209                   frag->ofs + fragofs+readlen,
0210                   ref_offset(frag->node->raw),
0211                   ref_flags(frag->node->raw));
0212             ret = jffs2_read_dnode(c, f, frag->node, buf, fragofs + frag->ofs - frag->node->ofs, readlen);
0213             jffs2_dbg(2, "node read done\n");
0214             if (ret) {
0215                 jffs2_dbg(1, "%s(): error %d\n",
0216                       __func__, ret);
0217                 memset(buf, 0, readlen);
0218                 return ret;
0219             }
0220             buf += readlen;
0221             offset += readlen;
0222             frag = frag_next(frag);
0223             jffs2_dbg(2, "node read was OK. Looping\n");
0224         }
0225     }
0226     return 0;
0227 }
0228