wok-current diff linux64-cloop/stuff/cloop.u @ rev 17332

Up fxload (2008_10_13)
author Pascal Bellard <pascal.bellard@slitaz.org>
date Wed Nov 05 14:56:51 2014 +0100 (2014-11-05)
parents
children b30e264381c7
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/linux64-cloop/stuff/cloop.u	Wed Nov 05 14:56:51 2014 +0100
     1.3 @@ -0,0 +1,280 @@
     1.4 +--- cloop.h
     1.5 ++++ cloop.h
     1.6 +@@ -20,6 +20,75 @@
     1.7 + /* data_index (num_blocks 64bit pointers, network order)...      */
     1.8 + /* compressed data (gzip block compressed format)...             */
     1.9 + 
    1.10 ++struct cloop_tail
    1.11 ++{
    1.12 ++	u_int32_t table_size;
    1.13 ++	u_int32_t index_size;
    1.14 ++	u_int32_t num_blocks;
    1.15 ++};
    1.16 ++
    1.17 ++struct block_info
    1.18 ++{
    1.19 ++	loff_t offset;		/* 64-bit offsets of compressed block */
    1.20 ++	u_int32_t size;		/* 32-bit compressed block size */
    1.21 ++	u_int32_t optidx;	/* 32-bit index number */
    1.22 ++};
    1.23 ++
    1.24 ++static inline char *build_index(struct block_info *offsets, unsigned long n)
    1.25 ++{
    1.26 ++	u_int32_t *ofs32 = (u_int32_t *) offsets;
    1.27 ++	loff_t    *ofs64 = (loff_t *) offsets;
    1.28 ++	
    1.29 ++	if (ofs32[0] == 0) {
    1.30 ++		if (ofs32[2]) { /* ACCELERATED KNOPPIX V1.0 */
    1.31 ++			while (n--) {
    1.32 ++				offsets[n].offset = __be64_to_cpu(offsets[n].offset);
    1.33 ++				offsets[n].size = ntohl(offsets[n].size);
    1.34 ++			}
    1.35 ++			return (char *) "128BE accelerated knoppix 1.0";
    1.36 ++		}
    1.37 ++		else { /* V2.0 */
    1.38 ++			loff_t last = __be64_to_cpu(ofs64[n]);
    1.39 ++			while (n--) {
    1.40 ++				offsets[n].size = last - 
    1.41 ++					(offsets[n].offset = __be64_to_cpu(ofs64[n])); 
    1.42 ++				last = offsets[n].offset;
    1.43 ++			}
    1.44 ++			return (char *) "64BE v2.0";
    1.45 ++		}
    1.46 ++	}
    1.47 ++	else if (ofs32[1] == 0) { /* V1.0 */
    1.48 ++		loff_t last = __le64_to_cpu(ofs64[n]);
    1.49 ++		while (n--) {
    1.50 ++			offsets[n].size = last - 
    1.51 ++				(offsets[n].offset = __le64_to_cpu(ofs64[n])); 
    1.52 ++			last = offsets[n].offset;
    1.53 ++		}
    1.54 ++		return (char *) "64LE v1.0";
    1.55 ++	}
    1.56 ++	else if (ntohl(ofs32[0]) == (4*n) + 0x8C) { /* V0.68 */
    1.57 ++		loff_t last = ntohl(ofs32[n]);
    1.58 ++		while (n--) {
    1.59 ++			offsets[n].size = last - 
    1.60 ++				(offsets[n].offset = ntohl(ofs32[n])); 
    1.61 ++			last = offsets[n].offset;
    1.62 ++		}
    1.63 ++		return (char *) "32BE v0.68";
    1.64 ++	}
    1.65 ++	else { /* V3.0 */
    1.66 ++		unsigned long i;
    1.67 ++		loff_t j;
    1.68 ++		
    1.69 ++		for (i = n; i-- != 0; )
    1.70 ++			offsets[i].size = ntohl(ofs32[i]); 
    1.71 ++		for (i = 0, j = sizeof(struct cloop_head); i < n; i++) {
    1.72 ++			offsets[i].offset = j;
    1.73 ++			j += offsets[i].size;
    1.74 ++		}
    1.75 ++		return (char *) "32BE v3.0";
    1.76 ++	}
    1.77 ++}
    1.78 ++
    1.79 + /* Cloop suspend IOCTL */
    1.80 + #define CLOOP_SUSPEND 0x4C07
    1.81 + 
    1.82 +--- cloop.c
    1.83 ++++ cloop.c
    1.84 +@@ -5,11 +5,18 @@
    1.85 +  *  A cloop file looks like this:
    1.86 +  *  [32-bit uncompressed block size: network order]
    1.87 +  *  [32-bit number of blocks (n_blocks): network order]
    1.88 +- *  [64-bit file offsets of start of blocks: network order]
    1.89 ++ *  [for version < 3]
    1.90 ++ *     [32-bit, 64-bit or 128-bit file offsets of start of blocks]
    1.91 +  *    ...
    1.92 +  *    (n_blocks + 1).
    1.93 +  * n_blocks consisting of:
    1.94 +  *   [compressed block]
    1.95 ++ *    ...
    1.96 ++ *  [for version >= 3]
    1.97 ++ *     [compressed list of 32-bit block sizes]
    1.98 ++ *     [32-bit compressed index size: network order]
    1.99 ++ *     [32-bit index size = 4: network order]
   1.100 ++ *     [32-bit number of blocks (n_blocks): network order]
   1.101 +  *
   1.102 +  * Every version greatly inspired by code seen in loop.c
   1.103 +  * by Theodore Ts'o, 3/29/93.
   1.104 +@@ -115,7 +122,7 @@
   1.105 +  struct cloop_head head;
   1.106 + 
   1.107 +  /* An array of offsets of compressed blocks within the file */
   1.108 +- loff_t *offsets;
   1.109 ++ struct block_info *offsets;
   1.110 + 
   1.111 +  /* We buffer some uncompressed blocks for performance */
   1.112 +  int buffered_blocknum[BUFFERED_BLOCKS];
   1.113 +@@ -256,11 +263,11 @@
   1.114 +     return i;
   1.115 +    }
   1.116 + 
   1.117 +- buf_length = be64_to_cpu(clo->offsets[blocknum+1]) - be64_to_cpu(clo->offsets[blocknum]);
   1.118 ++ buf_length = clo->offsets[blocknum].size;
   1.119 + 
   1.120 + /* Load one compressed block from the file. */
   1.121 +  cloop_read_from_file(clo, clo->backing_file, (char *)clo->compressed_buffer,
   1.122 +-                    be64_to_cpu(clo->offsets[blocknum]), buf_length);
   1.123 ++                    clo->offsets[blocknum].offset, buf_length);
   1.124 + 
   1.125 +  buflen = ntohl(clo->head.block_size);
   1.126 + 
   1.127 +@@ -275,9 +282,9 @@
   1.128 +  if (ret != 0)
   1.129 +   {
   1.130 +    printk(KERN_ERR "%s: zlib decompression error %i uncompressing block %u %u/%lu/%u/%u "
   1.131 +-          "%Lu-%Lu\n", cloop_name, ret, blocknum,
   1.132 ++          "%Lu:%u\n", cloop_name, ret, blocknum,
   1.133 + 	  ntohl(clo->head.block_size), buflen, buf_length, buf_done,
   1.134 +-	  be64_to_cpu(clo->offsets[blocknum]), be64_to_cpu(clo->offsets[blocknum+1]));
   1.135 ++	  clo->offsets[blocknum].offset, clo->offsets[blocknum].size);
   1.136 +    clo->buffered_blocknum[clo->current_bufnum] = -1;
   1.137 +    return -1;
   1.138 +   }
   1.139 +@@ -489,30 +496,73 @@
   1.140 +               cloop_name, ntohl(clo->head.block_size));
   1.141 +        error=-EBADF; goto error_release;
   1.142 +       }
   1.143 +-     if (clo->head.preamble[0x0B]!='V'||clo->head.preamble[0x0C]<'1')
   1.144 +-      {
   1.145 +-       printk(KERN_ERR "%s: Cannot read old 32-bit (version 0.68) images, "
   1.146 +-		       "please use an older version of %s for this file.\n",
   1.147 +-		       cloop_name, cloop_name);
   1.148 +-       error=-EBADF; goto error_release;
   1.149 +-      }
   1.150 +-     if (clo->head.preamble[0x0C]<'2')
   1.151 +-      {
   1.152 +-       printk(KERN_ERR "%s: Cannot read old architecture-dependent "
   1.153 +-		       "(format <= 1.0) images, please use an older "
   1.154 +-		       "version of %s for this file.\n",
   1.155 +-		       cloop_name, cloop_name);
   1.156 +-       error=-EBADF; goto error_release;
   1.157 +-      }
   1.158 +-     total_offsets=ntohl(clo->head.num_blocks)+1;
   1.159 +-     if (!isblkdev && (sizeof(struct cloop_head)+sizeof(loff_t)*
   1.160 ++     total_offsets=ntohl(clo->head.num_blocks);
   1.161 ++     if (!isblkdev && (sizeof(struct cloop_head)+sizeof(struct block_info)*
   1.162 +                        total_offsets > inode->i_size))
   1.163 +       {
   1.164 +        printk(KERN_ERR "%s: file too small for %u blocks\n",
   1.165 +               cloop_name, ntohl(clo->head.num_blocks));
   1.166 +        error=-EBADF; goto error_release;
   1.167 +       }
   1.168 +-     clo->offsets = cloop_malloc(sizeof(loff_t) * total_offsets);
   1.169 ++     if (total_offsets + 1 == 0) /* Version >= 3.0 */
   1.170 ++      {
   1.171 ++	struct cloop_tail tail;
   1.172 ++	if(isblkdev)
   1.173 ++	 {
   1.174 ++	 /* No end of file: can't find index */
   1.175 ++          printk(KERN_ERR "%s: no V3 support for block device\n",
   1.176 ++                 cloop_name);
   1.177 ++          error=-EBADF; goto error_release;
   1.178 ++	 }
   1.179 ++	bytes_read = cloop_read_from_file(clo, file, (void *) &tail,
   1.180 ++                          inode->i_size - sizeof(struct cloop_tail),
   1.181 ++			  sizeof(struct cloop_tail));
   1.182 ++	if(bytes_read == sizeof(struct cloop_tail))
   1.183 ++	 {
   1.184 ++	  unsigned long len, zlen;
   1.185 ++	  void *zbuf;
   1.186 ++          clo->head.num_blocks = tail.num_blocks;
   1.187 ++          total_offsets = ntohl(clo->head.num_blocks);
   1.188 ++          clo->offsets = cloop_malloc(sizeof(struct block_info) * total_offsets);
   1.189 ++	  if (!clo->offsets)
   1.190 ++	   {
   1.191 ++            printk(KERN_ERR "%s: can't alloc index\n",
   1.192 ++                   cloop_name);
   1.193 ++            error=-EBADF; goto error_release;
   1.194 ++	   }
   1.195 ++	  zbuf = &clo->offsets[total_offsets/2];
   1.196 ++	  zlen = ntohl(tail.table_size);
   1.197 ++	  len = ntohl(tail.index_size) * total_offsets;
   1.198 ++	  bytes_read = cloop_read_from_file(clo, file, zbuf,
   1.199 ++                          inode->i_size - zlen - sizeof(struct cloop_tail),
   1.200 ++			  zlen);
   1.201 ++	  if (bytes_read != zlen)
   1.202 ++	   {
   1.203 ++            printk(KERN_ERR "%s: can't read index\n",
   1.204 ++                   cloop_name);
   1.205 ++            error=-EBADF; goto error_release;
   1.206 ++	   }
   1.207 ++	  clo->zstream.workspace = cloop_malloc(zlib_inflate_workspacesize());
   1.208 ++	  if(!clo->zstream.workspace)
   1.209 ++	   {
   1.210 ++            printk(KERN_ERR "%s: can't alloc index workspace\n",
   1.211 ++                   cloop_name);
   1.212 ++            error=-EBADF; goto error_release;
   1.213 ++	   }
   1.214 ++	  zlib_inflateInit(&clo->zstream);
   1.215 ++	  uncompress(clo, (void *) clo->offsets, &len, zbuf, zlen);
   1.216 ++	  cloop_free(clo->zstream.workspace, zlib_inflate_workspacesize());
   1.217 ++	  clo->zstream.workspace = NULL;
   1.218 ++	  break;
   1.219 ++	 }
   1.220 ++	else
   1.221 ++	 {
   1.222 ++          printk(KERN_ERR "%s: can't find index\n",
   1.223 ++                 cloop_name);
   1.224 ++          error=-EBADF; goto error_release;
   1.225 ++	 }
   1.226 ++      }
   1.227 ++     clo->offsets = cloop_malloc(sizeof(struct block_info) * total_offsets);
   1.228 +      if (!clo->offsets)
   1.229 +       {
   1.230 +        printk(KERN_ERR "%s: out of kernel mem for offsets\n", cloop_name);
   1.231 +@@ -521,19 +571,19 @@
   1.232 +     }
   1.233 +    num_readable = MIN(total_offsets - offsets_read,
   1.234 +                       (clo->underlying_blksize - offset) 
   1.235 +-                      / sizeof(loff_t));
   1.236 +-   memcpy(&clo->offsets[offsets_read], bbuf+offset, num_readable * sizeof(loff_t));
   1.237 ++                      / sizeof(struct block_info));
   1.238 ++   memcpy(&clo->offsets[offsets_read], bbuf+offset, num_readable * sizeof(struct block_info));
   1.239 +    offsets_read += num_readable;
   1.240 +   }
   1.241 +   { /* Search for largest block rather than estimate. KK. */
   1.242 +    int i;
   1.243 +-   for(i=0;i<total_offsets-1;i++)
   1.244 ++   char *version = build_index(clo->offsets, ntohl(clo->head.num_blocks));
   1.245 ++   for(i=0;i<total_offsets;i++)
   1.246 +     {
   1.247 +-     loff_t d=be64_to_cpu(clo->offsets[i+1]) - be64_to_cpu(clo->offsets[i]);
   1.248 +-     clo->largest_block=MAX(clo->largest_block,d);
   1.249 ++     clo->largest_block=MAX(clo->largest_block,clo->offsets[i].size);
   1.250 +     }
   1.251 +-   printk(KERN_INFO "%s: %s: %u blocks, %u bytes/block, largest block is %lu bytes.\n",
   1.252 +-          cloop_name, filename, ntohl(clo->head.num_blocks),
   1.253 ++   printk(KERN_INFO "%s: %s: %s, %u blocks, %u bytes/block, largest block is %lu bytes.\n",
   1.254 ++          cloop_name, filename, version, ntohl(clo->head.num_blocks),
   1.255 +           ntohl(clo->head.block_size), clo->largest_block);
   1.256 +   }
   1.257 + /* Combo kmalloc used too large chunks (>130000). */
   1.258 +@@ -565,16 +615,6 @@
   1.259 +    error=-ENOMEM; goto error_release_free_all;
   1.260 +   }
   1.261 +  zlib_inflateInit(&clo->zstream);
   1.262 +- if(!isblkdev &&
   1.263 +-    be64_to_cpu(clo->offsets[ntohl(clo->head.num_blocks)]) != inode->i_size)
   1.264 +-  {
   1.265 +-   printk(KERN_ERR "%s: final offset wrong (%Lu not %Lu)\n",
   1.266 +-          cloop_name,
   1.267 +-          be64_to_cpu(clo->offsets[ntohl(clo->head.num_blocks)]),
   1.268 +-          inode->i_size);
   1.269 +-   cloop_free(clo->zstream.workspace, zlib_inflate_workspacesize()); clo->zstream.workspace=NULL;
   1.270 +-   goto error_release_free_all;
   1.271 +-  }
   1.272 +  {
   1.273 +   int i;
   1.274 +   for(i=0; i<BUFFERED_BLOCKS; i++) clo->buffered_blocknum[i] = -1;
   1.275 +@@ -653,7 +693,7 @@
   1.276 +    }
   1.277 +  }
   1.278 + error_release_free:
   1.279 +- cloop_free(clo->offsets, sizeof(loff_t) * total_offsets);
   1.280 ++ cloop_free(clo->offsets, sizeof(struct block_info) * total_offsets);
   1.281 +  clo->offsets=NULL;
   1.282 + error_release:
   1.283 +  if(bbuf) cloop_free(bbuf, clo->underlying_blksize);