linux-old/fs/jffs2/read.c
<<
>>
Prefs
   1/*
   2 * JFFS2 -- Journalling Flash File System, Version 2.
   3 *
   4 * Copyright (C) 2001 Red Hat, Inc.
   5 *
   6 * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
   7 *
   8 * The original JFFS, from which the design for JFFS2 was derived,
   9 * was designed and implemented by Axis Communications AB.
  10 *
  11 * The contents of this file are subject to the Red Hat eCos Public
  12 * License Version 1.1 (the "Licence"); you may not use this file
  13 * except in compliance with the Licence.  You may obtain a copy of
  14 * the Licence at http://www.redhat.com/
  15 *
  16 * Software distributed under the Licence is distributed on an "AS IS"
  17 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
  18 * See the Licence for the specific language governing rights and
  19 * limitations under the Licence.
  20 *
  21 * The Original Code is JFFS2 - Journalling Flash File System, version 2
  22 *
  23 * Alternatively, the contents of this file may be used under the
  24 * terms of the GNU General Public License version 2 (the "GPL"), in
  25 * which case the provisions of the GPL are applicable instead of the
  26 * above.  If you wish to allow the use of your version of this file
  27 * only under the terms of the GPL and not to allow others to use your
  28 * version of this file under the RHEPL, indicate your decision by
  29 * deleting the provisions above and replace them with the notice and
  30 * other provisions required by the GPL.  If you do not delete the
  31 * provisions above, a recipient may use your version of this file
  32 * under either the RHEPL or the GPL.
  33 *
  34 * $Id: read.c,v 1.13.2.2 2003/11/02 13:51:18 dwmw2 Exp $
  35 *
  36 */
  37
  38#include <linux/kernel.h>
  39#include <linux/slab.h>
  40#include <linux/jffs2.h>
  41#include <linux/mtd/mtd.h>
  42#include "nodelist.h"
  43#include <linux/crc32.h>
  44
  45int jffs2_read_dnode(struct jffs2_sb_info *c, struct jffs2_full_dnode *fd, unsigned char *buf, int ofs, int len)
  46{
  47        struct jffs2_raw_inode *ri;
  48        size_t readlen;
  49        __u32 crc;
  50        unsigned char *decomprbuf = NULL;
  51        unsigned char *readbuf = NULL;
  52        int ret = 0;
  53
  54        ri = jffs2_alloc_raw_inode();
  55        if (!ri)
  56                return -ENOMEM;
  57
  58        ret = c->mtd->read(c->mtd, fd->raw->flash_offset & ~3, sizeof(*ri), &readlen, (char *)ri);
  59        if (ret) {
  60                jffs2_free_raw_inode(ri);
  61                printk(KERN_WARNING "Error reading node from 0x%08x: %d\n", fd->raw->flash_offset & ~3, ret);
  62                return ret;
  63        }
  64        if (readlen != sizeof(*ri)) {
  65                jffs2_free_raw_inode(ri);
  66                printk(KERN_WARNING "Short read from 0x%08x: wanted 0x%x bytes, got 0x%x\n", 
  67                       fd->raw->flash_offset & ~3, sizeof(*ri), readlen);
  68                return -EIO;
  69        }
  70        crc = crc32(0, ri, sizeof(*ri)-8);
  71
  72        D1(printk(KERN_DEBUG "Node read from %08x: node_crc %08x, calculated CRC %08x. dsize %x, csize %x, offset %x, buf %p\n", fd->raw->flash_offset & ~3, ri->node_crc, crc, ri->dsize, ri->csize, ri->offset, buf));
  73        if (crc != ri->node_crc) {
  74                printk(KERN_WARNING "Node CRC %08x != calculated CRC %08x for node at %08x\n", ri->node_crc, crc, fd->raw->flash_offset & ~3);
  75                ret = -EIO;
  76                goto out_ri;
  77        }
  78        /* There was a bug where we wrote hole nodes out with csize/dsize
  79           swapped. Deal with it */
  80        if (ri->compr == JFFS2_COMPR_ZERO && !ri->dsize && ri->csize) {
  81                ri->dsize = ri->csize;
  82                ri->csize = 0;
  83        }
  84
  85        D1(if(ofs + len > ri->dsize) {
  86                printk(KERN_WARNING "jffs2_read_dnode() asked for %d bytes at %d from %d-byte node\n", len, ofs, ri->dsize);
  87                ret = -EINVAL;
  88                goto out_ri;
  89        });
  90
  91        
  92        if (ri->compr == JFFS2_COMPR_ZERO) {
  93                memset(buf, 0, len);
  94                goto out_ri;
  95        }
  96
  97        /* Cases:
  98           Reading whole node and it's uncompressed - read directly to buffer provided, check CRC.
  99           Reading whole node and it's compressed - read into comprbuf, check CRC and decompress to buffer provided 
 100           Reading partial node and it's uncompressed - read into readbuf, check CRC, and copy 
 101           Reading partial node and it's compressed - read into readbuf, check checksum, decompress to decomprbuf and copy
 102        */
 103        if (ri->compr == JFFS2_COMPR_NONE && len == ri->dsize) {
 104                readbuf = buf;
 105        } else {
 106                readbuf = kmalloc(ri->csize, GFP_KERNEL);
 107                if (!readbuf) {
 108                        ret = -ENOMEM;
 109                        goto out_ri;
 110                }
 111        }
 112        if (ri->compr != JFFS2_COMPR_NONE) {
 113                if (len < ri->dsize) {
 114                        decomprbuf = kmalloc(ri->dsize, GFP_KERNEL);
 115                        if (!decomprbuf) {
 116                                ret = -ENOMEM;
 117                                goto out_readbuf;
 118                        }
 119                } else {
 120                        decomprbuf = buf;
 121                }
 122        } else {
 123                decomprbuf = readbuf;
 124        }
 125
 126        D2(printk(KERN_DEBUG "Read %d bytes to %p\n", ri->csize, readbuf));
 127        ret = c->mtd->read(c->mtd, (fd->raw->flash_offset &~3) + sizeof(*ri), ri->csize, &readlen, readbuf);
 128
 129        if (!ret && readlen != ri->csize)
 130                ret = -EIO;
 131        if (ret)
 132                goto out_decomprbuf;
 133
 134        crc = crc32(0, readbuf, ri->csize);
 135        if (crc != ri->data_crc) {
 136                printk(KERN_WARNING "Data CRC %08x != calculated CRC %08x for node at %08x\n", ri->data_crc, crc, fd->raw->flash_offset & ~3);
 137                ret = -EIO;
 138                goto out_decomprbuf;
 139        }
 140        D2(printk(KERN_DEBUG "Data CRC matches calculated CRC %08x\n", crc));
 141        if (ri->compr != JFFS2_COMPR_NONE) {
 142                D2(printk(KERN_DEBUG "Decompress %d bytes from %p to %d bytes at %p\n", ri->csize, readbuf, ri->dsize, decomprbuf)); 
 143                ret = jffs2_decompress(ri->compr, readbuf, decomprbuf, ri->csize, ri->dsize);
 144                if (ret) {
 145                        printk(KERN_WARNING "Error: jffs2_decompress returned %d\n", ret);
 146                        goto out_decomprbuf;
 147                }
 148        }
 149
 150        if (len < ri->dsize) {
 151                memcpy(buf, decomprbuf+ofs, len);
 152        }
 153 out_decomprbuf:
 154        if(decomprbuf != buf && decomprbuf != readbuf)
 155                kfree(decomprbuf);
 156 out_readbuf:
 157        if(readbuf != buf)
 158                kfree(readbuf);
 159 out_ri:
 160        jffs2_free_raw_inode(ri);
 161
 162        return ret;
 163}
 164
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.