LCOV - code coverage report
Current view: top level - fs/jffs2 - read.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 75 0.0 %
Date: 2014-02-18 Functions: 0 2 0.0 %
Branches: 0 72 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * JFFS2 -- Journalling Flash File System, Version 2.
       3                 :            :  *
       4                 :            :  * Copyright © 2001-2007 Red Hat, Inc.
       5                 :            :  *
       6                 :            :  * Created by David Woodhouse <dwmw2@infradead.org>
       7                 :            :  *
       8                 :            :  * For licensing information, see the file 'LICENCE' in this directory.
       9                 :            :  *
      10                 :            :  */
      11                 :            : 
      12                 :            : #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
      13                 :            : 
      14                 :            : #include <linux/kernel.h>
      15                 :            : #include <linux/slab.h>
      16                 :            : #include <linux/crc32.h>
      17                 :            : #include <linux/pagemap.h>
      18                 :            : #include <linux/mtd/mtd.h>
      19                 :            : #include <linux/compiler.h>
      20                 :            : #include "nodelist.h"
      21                 :            : #include "compr.h"
      22                 :            : 
      23                 :          0 : int jffs2_read_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
      24                 :            :                      struct jffs2_full_dnode *fd, unsigned char *buf,
      25                 :            :                      int ofs, int len)
      26                 :            : {
      27                 :            :         struct jffs2_raw_inode *ri;
      28                 :            :         size_t readlen;
      29                 :            :         uint32_t crc;
      30                 :            :         unsigned char *decomprbuf = NULL;
      31                 :            :         unsigned char *readbuf = NULL;
      32                 :            :         int ret = 0;
      33                 :            : 
      34                 :          0 :         ri = jffs2_alloc_raw_inode();
      35         [ #  # ]:          0 :         if (!ri)
      36                 :            :                 return -ENOMEM;
      37                 :            : 
      38                 :          0 :         ret = jffs2_flash_read(c, ref_offset(fd->raw), sizeof(*ri), &readlen, (char *)ri);
      39         [ #  # ]:          0 :         if (ret) {
      40                 :          0 :                 jffs2_free_raw_inode(ri);
      41                 :          0 :                 pr_warn("Error reading node from 0x%08x: %d\n",
      42                 :            :                         ref_offset(fd->raw), ret);
      43                 :          0 :                 return ret;
      44                 :            :         }
      45         [ #  # ]:          0 :         if (readlen != sizeof(*ri)) {
      46                 :          0 :                 jffs2_free_raw_inode(ri);
      47                 :          0 :                 pr_warn("Short read from 0x%08x: wanted 0x%zx bytes, got 0x%zx\n",
      48                 :            :                         ref_offset(fd->raw), sizeof(*ri), readlen);
      49                 :          0 :                 return -EIO;
      50                 :            :         }
      51                 :          0 :         crc = crc32(0, ri, sizeof(*ri)-8);
      52                 :            : 
      53                 :            :         jffs2_dbg(1, "Node read from %08x: node_crc %08x, calculated CRC %08x. dsize %x, csize %x, offset %x, buf %p\n",
      54                 :            :                   ref_offset(fd->raw), je32_to_cpu(ri->node_crc),
      55                 :            :                   crc, je32_to_cpu(ri->dsize), je32_to_cpu(ri->csize),
      56                 :            :                   je32_to_cpu(ri->offset), buf);
      57         [ #  # ]:          0 :         if (crc != je32_to_cpu(ri->node_crc)) {
      58                 :          0 :                 pr_warn("Node CRC %08x != calculated CRC %08x for node at %08x\n",
      59                 :            :                         je32_to_cpu(ri->node_crc), crc, ref_offset(fd->raw));
      60                 :            :                 ret = -EIO;
      61                 :          0 :                 goto out_ri;
      62                 :            :         }
      63                 :            :         /* There was a bug where we wrote hole nodes out with csize/dsize
      64                 :            :            swapped. Deal with it */
      65 [ #  # ][ #  # ]:          0 :         if (ri->compr == JFFS2_COMPR_ZERO && !je32_to_cpu(ri->dsize) &&
                 [ #  # ]
      66                 :          0 :             je32_to_cpu(ri->csize)) {
      67                 :          0 :                 ri->dsize = ri->csize;
      68                 :          0 :                 ri->csize = cpu_to_je32(0);
      69                 :            :         }
      70                 :            : 
      71                 :            :         D1(if(ofs + len > je32_to_cpu(ri->dsize)) {
      72                 :            :                         pr_warn("jffs2_read_dnode() asked for %d bytes at %d from %d-byte node\n",
      73                 :            :                                 len, ofs, je32_to_cpu(ri->dsize));
      74                 :            :                 ret = -EINVAL;
      75                 :            :                 goto out_ri;
      76                 :            :         });
      77                 :            : 
      78                 :            : 
      79         [ #  # ]:          0 :         if (ri->compr == JFFS2_COMPR_ZERO) {
      80         [ #  # ]:          0 :                 memset(buf, 0, len);
      81                 :            :                 goto out_ri;
      82                 :            :         }
      83                 :            : 
      84                 :            :         /* Cases:
      85                 :            :            Reading whole node and it's uncompressed - read directly to buffer provided, check CRC.
      86                 :            :            Reading whole node and it's compressed - read into comprbuf, check CRC and decompress to buffer provided
      87                 :            :            Reading partial node and it's uncompressed - read into readbuf, check CRC, and copy
      88                 :            :            Reading partial node and it's compressed - read into readbuf, check checksum, decompress to decomprbuf and copy
      89                 :            :         */
      90 [ #  # ][ #  # ]:          0 :         if (ri->compr == JFFS2_COMPR_NONE && len == je32_to_cpu(ri->dsize)) {
      91                 :            :                 readbuf = buf;
      92                 :            :         } else {
      93                 :          0 :                 readbuf = kmalloc(je32_to_cpu(ri->csize), GFP_KERNEL);
      94         [ #  # ]:          0 :                 if (!readbuf) {
      95                 :            :                         ret = -ENOMEM;
      96                 :            :                         goto out_ri;
      97                 :            :                 }
      98                 :            :         }
      99         [ #  # ]:          0 :         if (ri->compr != JFFS2_COMPR_NONE) {
     100         [ #  # ]:          0 :                 if (len < je32_to_cpu(ri->dsize)) {
     101                 :            :                         decomprbuf = kmalloc(je32_to_cpu(ri->dsize), GFP_KERNEL);
     102         [ #  # ]:          0 :                         if (!decomprbuf) {
     103                 :            :                                 ret = -ENOMEM;
     104                 :            :                                 goto out_readbuf;
     105                 :            :                         }
     106                 :            :                 } else {
     107                 :            :                         decomprbuf = buf;
     108                 :            :                 }
     109                 :            :         } else {
     110                 :            :                 decomprbuf = readbuf;
     111                 :            :         }
     112                 :            : 
     113                 :            :         jffs2_dbg(2, "Read %d bytes to %p\n", je32_to_cpu(ri->csize),
     114                 :            :                   readbuf);
     115                 :          0 :         ret = jffs2_flash_read(c, (ref_offset(fd->raw)) + sizeof(*ri),
     116                 :            :                                je32_to_cpu(ri->csize), &readlen, readbuf);
     117                 :            : 
     118 [ #  # ][ #  # ]:          0 :         if (!ret && readlen != je32_to_cpu(ri->csize))
     119                 :            :                 ret = -EIO;
     120         [ #  # ]:          0 :         if (ret)
     121                 :            :                 goto out_decomprbuf;
     122                 :            : 
     123                 :          0 :         crc = crc32(0, readbuf, je32_to_cpu(ri->csize));
     124         [ #  # ]:          0 :         if (crc != je32_to_cpu(ri->data_crc)) {
     125                 :          0 :                 pr_warn("Data CRC %08x != calculated CRC %08x for node at %08x\n",
     126                 :            :                         je32_to_cpu(ri->data_crc), crc, ref_offset(fd->raw));
     127                 :            :                 ret = -EIO;
     128                 :          0 :                 goto out_decomprbuf;
     129                 :            :         }
     130                 :            :         jffs2_dbg(2, "Data CRC matches calculated CRC %08x\n", crc);
     131         [ #  # ]:          0 :         if (ri->compr != JFFS2_COMPR_NONE) {
     132                 :            :                 jffs2_dbg(2, "Decompress %d bytes from %p to %d bytes at %p\n",
     133                 :            :                           je32_to_cpu(ri->csize), readbuf,
     134                 :            :                           je32_to_cpu(ri->dsize), decomprbuf);
     135                 :          0 :                 ret = jffs2_decompress(c, f, ri->compr | (ri->usercompr << 8), readbuf, decomprbuf, je32_to_cpu(ri->csize), je32_to_cpu(ri->dsize));
     136         [ #  # ]:          0 :                 if (ret) {
     137                 :          0 :                         pr_warn("Error: jffs2_decompress returned %d\n", ret);
     138                 :          0 :                         goto out_decomprbuf;
     139                 :            :                 }
     140                 :            :         }
     141                 :            : 
     142         [ #  # ]:          0 :         if (len < je32_to_cpu(ri->dsize)) {
     143                 :          0 :                 memcpy(buf, decomprbuf+ofs, len);
     144                 :            :         }
     145                 :            :  out_decomprbuf:
     146         [ #  # ]:          0 :         if(decomprbuf != buf && decomprbuf != readbuf)
     147                 :          0 :                 kfree(decomprbuf);
     148                 :            :  out_readbuf:
     149         [ #  # ]:          0 :         if(readbuf != buf)
     150                 :          0 :                 kfree(readbuf);
     151                 :            :  out_ri:
     152                 :          0 :         jffs2_free_raw_inode(ri);
     153                 :            : 
     154                 :          0 :         return ret;
     155                 :            : }
     156                 :            : 
     157                 :          0 : int jffs2_read_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
     158                 :            :                            unsigned char *buf, uint32_t offset, uint32_t len)
     159                 :            : {
     160                 :          0 :         uint32_t end = offset + len;
     161                 :            :         struct jffs2_node_frag *frag;
     162                 :            :         int ret;
     163                 :            : 
     164                 :            :         jffs2_dbg(1, "%s(): ino #%u, range 0x%08x-0x%08x\n",
     165                 :            :                   __func__, f->inocache->ino, offset, offset + len);
     166                 :            : 
     167                 :          0 :         frag = jffs2_lookup_node_frag(&f->fragtree, offset);
     168                 :            : 
     169                 :            :         /* XXX FIXME: Where a single physical node actually shows up in two
     170                 :            :            frags, we read it twice. Don't do that. */
     171                 :            :         /* Now we're pointing at the first frag which overlaps our page
     172                 :            :          * (or perhaps is before it, if we've been asked to read off the
     173                 :            :          * end of the file). */
     174         [ #  # ]:          0 :         while(offset < end) {
     175                 :            :                 jffs2_dbg(2, "%s(): offset %d, end %d\n",
     176                 :            :                           __func__, offset, end);
     177 [ #  # ][ #  # ]:          0 :                 if (unlikely(!frag || frag->ofs > offset ||
         [ #  # ][ #  # ]
     178                 :            :                              frag->ofs + frag->size <= offset)) {
     179                 :          0 :                         uint32_t holesize = end - offset;
     180 [ #  # ][ #  # ]:          0 :                         if (frag && frag->ofs > offset) {
     181                 :            :                                 jffs2_dbg(1, "Eep. Hole in ino #%u fraglist. frag->ofs = 0x%08x, offset = 0x%08x\n",
     182                 :            :                                           f->inocache->ino, frag->ofs, offset);
     183                 :          0 :                                 holesize = min(holesize, frag->ofs - offset);
     184                 :            :                         }
     185                 :            :                         jffs2_dbg(1, "Filling non-frag hole from %d-%d\n",
     186                 :            :                                   offset, offset + holesize);
     187         [ #  # ]:          0 :                         memset(buf, 0, holesize);
     188                 :          0 :                         buf += holesize;
     189                 :          0 :                         offset += holesize;
     190                 :          0 :                         continue;
     191         [ #  # ]:          0 :                 } else if (unlikely(!frag->node)) {
     192                 :          0 :                         uint32_t holeend = min(end, frag->ofs + frag->size);
     193                 :            :                         jffs2_dbg(1, "Filling frag hole from %d-%d (frag 0x%x 0x%x)\n",
     194                 :            :                                   offset, holeend, frag->ofs,
     195                 :            :                                   frag->ofs + frag->size);
     196         [ #  # ]:          0 :                         memset(buf, 0, holeend - offset);
     197                 :          0 :                         buf += holeend - offset;
     198                 :            :                         offset = holeend;
     199                 :          0 :                         frag = frag_next(frag);
     200                 :          0 :                         continue;
     201                 :            :                 } else {
     202                 :            :                         uint32_t readlen;
     203                 :            :                         uint32_t fragofs; /* offset within the frag to start reading */
     204                 :            : 
     205                 :          0 :                         fragofs = offset - frag->ofs;
     206                 :          0 :                         readlen = min(frag->size - fragofs, end - offset);
     207                 :            :                         jffs2_dbg(1, "Reading %d-%d from node at 0x%08x (%d)\n",
     208                 :            :                                   frag->ofs+fragofs,
     209                 :            :                                   frag->ofs + fragofs+readlen,
     210                 :            :                                   ref_offset(frag->node->raw),
     211                 :            :                                   ref_flags(frag->node->raw));
     212                 :          0 :                         ret = jffs2_read_dnode(c, f, frag->node, buf, fragofs + frag->ofs - frag->node->ofs, readlen);
     213                 :            :                         jffs2_dbg(2, "node read done\n");
     214         [ #  # ]:          0 :                         if (ret) {
     215                 :            :                                 jffs2_dbg(1, "%s(): error %d\n",
     216                 :            :                                           __func__, ret);
     217         [ #  # ]:          0 :                                 memset(buf, 0, readlen);
     218                 :          0 :                                 return ret;
     219                 :            :                         }
     220                 :          0 :                         buf += readlen;
     221                 :          0 :                         offset += readlen;
     222                 :          0 :                         frag = frag_next(frag);
     223                 :            :                         jffs2_dbg(2, "node read was OK. Looping\n");
     224                 :            :                 }
     225                 :            :         }
     226                 :            :         return 0;
     227                 :            : }
     228                 :            : 

Generated by: LCOV version 1.9