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 |