trunk/src/lib/util/chd.c
| r17995 | r17996 | |
| 540 | 540 | return CHDERR_ALREADY_OPEN; |
| 541 | 541 | |
| 542 | 542 | // set the header parameters |
| 543 | | m_version = HEADER_VERSION; |
| 544 | 543 | m_logicalbytes = logicalbytes; |
| 545 | | m_metaoffset = 0; |
| 546 | 544 | m_hunkbytes = hunkbytes; |
| 547 | | m_hunkcount = (m_logicalbytes + m_hunkbytes - 1) / m_hunkbytes; |
| 548 | 545 | m_unitbytes = unitbytes; |
| 549 | 546 | memcpy(m_compression, compression, sizeof(m_compression)); |
| 550 | 547 | m_parent = NULL; |
| r17995 | r17996 | |
| 568 | 565 | return CHDERR_ALREADY_OPEN; |
| 569 | 566 | |
| 570 | 567 | // set the header parameters |
| 571 | | m_version = HEADER_VERSION; |
| 572 | 568 | m_logicalbytes = logicalbytes; |
| 573 | | m_metaoffset = 0; |
| 574 | 569 | m_hunkbytes = hunkbytes; |
| 575 | | m_hunkcount = (m_logicalbytes + m_hunkbytes - 1) / m_hunkbytes; |
| 576 | 570 | m_unitbytes = parent.unit_bytes(); |
| 577 | 571 | memcpy(m_compression, compression, sizeof(m_compression)); |
| 578 | 572 | m_parent = &parent; |
| r17995 | r17996 | |
| 1475 | 1469 | |
| 1476 | 1470 | // extract parent SHA-1 |
| 1477 | 1471 | UINT32 flags = be_read(&rawheader[16], 4); |
| 1478 | | if ((flags & 2) && m_allow_writes) |
| 1479 | | throw CHDERR_FILE_NOT_WRITEABLE; |
| 1472 | m_allow_writes = (flags & 2) == 0; |
| 1480 | 1473 | |
| 1481 | 1474 | // determine compression |
| 1482 | 1475 | switch (be_read(&rawheader[20], 4)) |
| r17995 | r17996 | |
| 1529 | 1522 | |
| 1530 | 1523 | // extract parent SHA-1 |
| 1531 | 1524 | UINT32 flags = be_read(&rawheader[16], 4); |
| 1532 | | if ((flags & 2) && m_allow_writes) |
| 1533 | | throw CHDERR_FILE_NOT_WRITEABLE; |
| 1525 | m_allow_writes = (flags & 2) == 0; |
| 1534 | 1526 | |
| 1535 | 1527 | // determine compression |
| 1536 | 1528 | switch (be_read(&rawheader[20], 4)) |
| r17995 | r17996 | |
| 1589 | 1581 | m_compression[2] = be_read(&rawheader[24], 4); |
| 1590 | 1582 | m_compression[3] = be_read(&rawheader[28], 4); |
| 1591 | 1583 | |
| 1592 | | if (compressed() && m_allow_writes) |
| 1593 | | throw CHDERR_FILE_NOT_WRITEABLE; |
| 1584 | m_allow_writes = !compressed(); |
| 1594 | 1585 | |
| 1595 | 1586 | // describe the format |
| 1596 | 1587 | m_mapoffset_offset = 40; |
| r17995 | r17996 | |
| 1942 | 1933 | // wrap in try for proper error handling |
| 1943 | 1934 | try |
| 1944 | 1935 | { |
| 1936 | m_version = HEADER_VERSION; |
| 1937 | m_metaoffset = 0; |
| 1938 | |
| 1945 | 1939 | // if we have a parent, it must be V3 or later |
| 1946 | 1940 | if (m_parent != NULL && m_parent->version() < 3) |
| 1947 | 1941 | throw CHDERR_UNSUPPORTED_VERSION; |
| r17995 | r17996 | |
| 1952 | 1946 | if (m_parent != NULL && m_unitbytes != m_parent->unit_bytes()) |
| 1953 | 1947 | throw CHDERR_INVALID_PARAMETER; |
| 1954 | 1948 | |
| 1955 | | // writes are obviously permitted; reads only if uncompressed |
| 1956 | | m_allow_writes = true; |
| 1957 | | m_allow_reads = !compressed(); |
| 1958 | | |
| 1959 | 1949 | // verify the compression types |
| 1960 | 1950 | bool found_zero = false; |
| 1961 | 1951 | for (int codecnum = 0; codecnum < ARRAY_LENGTH(m_compression); codecnum++) |
| r17995 | r17996 | |
| 1970 | 1960 | } |
| 1971 | 1961 | |
| 1972 | 1962 | // create our V5 header |
| 1973 | | assert(m_version == HEADER_VERSION); |
| 1974 | 1963 | UINT8 rawheader[V5_HEADER_SIZE]; |
| 1975 | 1964 | memcpy(&rawheader[0], "MComprHD", 8); |
| 1976 | 1965 | be_write(&rawheader[8], V5_HEADER_SIZE, 4); |
| r17995 | r17996 | |
| 1995 | 1984 | sha1_t parentsha1; |
| 1996 | 1985 | parse_v5_header(rawheader, parentsha1); |
| 1997 | 1986 | |
| 1987 | // writes are obviously permitted; reads only if uncompressed |
| 1988 | m_allow_writes = true; |
| 1989 | m_allow_reads = !compressed(); |
| 1990 | |
| 1998 | 1991 | // write out the map (if not compressed) |
| 1999 | 1992 | if (!compressed()) |
| 2000 | 1993 | { |
| r17995 | r17996 | |
| 2039 | 2032 | // wrap in try for proper error handling |
| 2040 | 2033 | try |
| 2041 | 2034 | { |
| 2042 | | // reads are always permitted; writes possibly as well |
| 2035 | // reads are always permitted |
| 2043 | 2036 | m_allow_reads = true; |
| 2044 | | m_allow_writes = writeable; |
| 2045 | 2037 | |
| 2046 | 2038 | // read the raw header |
| 2047 | 2039 | UINT8 rawheader[MAX_HEADER_SIZE]; |
| r17995 | r17996 | |
| 2053 | 2045 | |
| 2054 | 2046 | // only allow writes to the most recent version |
| 2055 | 2047 | m_version = be_read(&rawheader[12], 4); |
| 2056 | | if (m_allow_writes && m_version < HEADER_VERSION) |
| 2048 | if (writeable && m_version < HEADER_VERSION) |
| 2057 | 2049 | throw CHDERR_UNSUPPORTED_VERSION; |
| 2058 | 2050 | |
| 2059 | 2051 | // read the header if we support it |
| r17995 | r17996 | |
| 2066 | 2058 | default: throw CHDERR_UNSUPPORTED_VERSION; |
| 2067 | 2059 | } |
| 2068 | 2060 | |
| 2061 | if (writeable && !m_allow_writes) |
| 2062 | throw CHDERR_FILE_NOT_WRITEABLE; |
| 2063 | |
| 2069 | 2064 | // make sure we have a parent if we need one (and don't if we don't) |
| 2070 | 2065 | if (parentsha1 != sha1_t::null) |
| 2071 | 2066 | { |
| r17995 | r17996 | |
| 2074 | 2069 | else if (m_parent->sha1() != parentsha1) |
| 2075 | 2070 | throw CHDERR_INVALID_PARENT; |
| 2076 | 2071 | } |
| 2077 | | else if (parentsha1 == sha1_t::null && m_parent != NULL) |
| 2072 | else if (m_parent != NULL) |
| 2078 | 2073 | throw CHDERR_INVALID_PARAMETER; |
| 2079 | 2074 | |
| 2080 | 2075 | // finish opening the file |