func: static int dmg_open(BlockDriverState *bs, const char *filename, int flags)
  
  {
  
      BDRVDMGState *s = bs->opaque;
  
      off_t info_begin,info_end,last_in_offset,last_out_offset;
  
      uint32_t count;
  
      uint32_t max_compressed_size=1,max_sectors_per_chunk=1,i;
  
      int64_t offset;
  
  
  
      s->fd = open(filename, O_RDONLY | O_BINARY);
  
      if (s->fd < 0)
  
          return -errno;
  
      bs->read_only = 1;
  
      s->n_chunks = 0;
  
      s->offsets = s->lengths = s->sectors = s->sectorcounts = NULL;
  
  
  
      /* read offset of info blocks */
  
      offset = lseek(s->fd, -0x1d8, SEEK_END);
  
      if (offset < 0) {
  
          goto fail;
  
      }
  
  
  
      info_begin = read_off(s->fd, offset);
  
      if (info_begin == 0) {
  
  	goto fail;
  
      }
  
  
  
      if (read_uint32(s->fd, info_begin) != 0x100) {
  
          goto fail;
  
      }
  
  
  
      count = read_uint32(s->fd, info_begin + 4);
  
      if (count == 0) {
  
          goto fail;
  
      }
  
      info_end = info_begin + count;
  
  
  
      offset = info_begin + 0x100;
  
  
  
      /* read offsets */
  
      last_in_offset = last_out_offset = 0;
  
      while (offset < info_end) {
  
          uint32_t type;
  
  
  
  	count = read_uint32(s->fd, offset);
  
  	if(count==0)
  
  	    goto fail;
  
          offset += 4;
  
  
  
  	type = read_uint32(s->fd, offset);
  
  	if (type == 0x6d697368 && count >= 244) {
  
  	    int new_size, chunk_count;
  
  
  
              offset += 4;
  
              offset += 200;
  
  
  
  	    chunk_count = (count-204)/40;
  
  	    new_size = sizeof(uint64_t) * (s->n_chunks + chunk_count);
  
  	    s->types = qemu_realloc(s->types, new_size/2);
  
  	    s->offsets = qemu_realloc(s->offsets, new_size);
  
  	    s->lengths = qemu_realloc(s->lengths, new_size);
  
  	    s->sectors = qemu_realloc(s->sectors, new_size);
  
  	    s->sectorcounts = qemu_realloc(s->sectorcounts, new_size);
  
  
  
  	    for(i=s->n_chunks;i<s->n_chunks+chunk_count;i++) {
  
  		s->types[i] = read_uint32(s->fd, offset);
  
  		offset += 4;
  
  		if(s->types[i]!=0x80000005 && s->types[i]!=1 && s->types[i]!=2) {
  
  		    if(s->types[i]==0xffffffff) {
  
  			last_in_offset = s->offsets[i-1]+s->lengths[i-1];
  
  			last_out_offset = s->sectors[i-1]+s->sectorcounts[i-1];
  
  		    }
  
  		    chunk_count--;
  
  		    i--;
  
  		    offset += 36;
  
  		    continue;
  
  		}
  
  		offset += 4;
  
  
  
  		s->sectors[i] = last_out_offset+read_off(s->fd, offset);
  
  		offset += 8;
  
  
  
  		s->sectorcounts[i] = read_off(s->fd, offset);
  
  		offset += 8;
  
  
  
  		s->offsets[i] = last_in_offset+read_off(s->fd, offset);
  
  		offset += 8;
  
  
  
  		s->lengths[i] = read_off(s->fd, offset);
  
  		offset += 8;
  
  
  
  		if(s->lengths[i]>max_compressed_size)
  
  		    max_compressed_size = s->lengths[i];
  
  		if(s->sectorcounts[i]>max_sectors_per_chunk)
  
  		    max_sectors_per_chunk = s->sectorcounts[i];
  
  	    }
  
  	    s->n_chunks+=chunk_count;
  
  	}
  
      }
  
  
  
      /* initialize zlib engine */
  
      s->compressed_chunk = qemu_malloc(max_compressed_size+1);
  
      s->uncompressed_chunk = qemu_malloc(512*max_sectors_per_chunk);
  
      if(inflateInit(&s->zstream) != Z_OK)
  
  	goto fail;
  
  
  
      s->current_chunk = s->n_chunks;
  
  
  
      return 0;
  
  fail:
  
      close(s->fd);
  
      return -1;
  
  }
  