+static FLAC__bool read_from_wave64_(foreign_metadata_t *fm, FILE *f, const char **error)
+{
+ FLAC__byte buffer[40];
+ FLAC__off_t offset, eof_offset = -1;
+ if((offset = ftello(f)) < 0) {
+ if(error) *error = "ftello() error (001)";
+ return false;
+ }
+ if(
+ fread(buffer, 1, 40, f) < 40 ||
+ /* RIFF GUID 66666972-912E-11CF-A5D6-28DB04C10000 */
+ memcmp(buffer, "\x72\x69\x66\x66\x2E\x91\xCF\x11\xA5\xD6\x28\xDB\x04\xC1\x00\x00", 16) ||
+ /* WAVE GUID 65766177-ACF3-11D3-8CD1-00C04F8EDB8A */
+ memcmp(buffer+24, "\x77\x61\x76\x65\xF3\xAC\xD3\x11\x8C\xD1\x00\xC0\x4F\x8E\xDB\x8A", 16)
+ ) {
+ if(error) *error = "unsupported Wave64 layout (002)";
+ return false;
+ }
+ if(sizeof(FLAC__off_t) < 8) {
+ if(error) *error = "Wave64 is not supported on this compile (r00)";
+ return false;
+ }
+ if(!append_block_(fm, offset, 40, error))
+ return false;
+ eof_offset = (FLAC__off_t)unpack64le_(buffer+16); /*@@@ [2^63 limit] */
+ while(!feof(f)) {
+ FLAC__uint64 size;
+ if((offset = ftello(f)) < 0) {
+ if(error) *error = "ftello() error (003)";
+ return false;
+ }
+ if((size = fread(buffer, 1, 24, f)) < 24) {
+ if(size == 0 && feof(f))
+ break;
+ if(error) *error = "invalid Wave64 file (004)";
+ return false;
+ }
+ size = unpack64le_(buffer+16);
+ /* check if pad bytes needed */
+ if(size & 7)
+ size = (size+7) & (~((FLAC__uint64)7));
+ /* fmt GUID 20746D66-ACF3-11D3-8CD1-00C04F8EDB8A */
+ if(!memcmp(buffer, "\x66\x6D\x74\x20\xF3\xAC\xD3\x11\x8C\xD1\x00\xC0\x4F\x8E\xDB\x8A", 16)) {
+ if(fm->format_block) {
+ if(error) *error = "invalid Wave64 file: multiple \"fmt \" chunks (005)";
+ return false;
+ }
+ if(fm->audio_block) {
+ if(error) *error = "invalid Wave64 file: \"data\" chunk before \"fmt \" chunk (006)";
+ return false;
+ }
+ fm->format_block = fm->num_blocks;
+ }
+ /* data GUID 61746164-ACF3-11D3-8CD1-00C04F8EDB8A */
+ else if(!memcmp(buffer, "\x64\x61\x74\x61\xF3\xAC\xD3\x11\x8C\xD1\x00\xC0\x4F\x8E\xDB\x8A", 16)) {
+ if(fm->audio_block) {
+ if(error) *error = "invalid Wave64 file: multiple \"data\" chunks (007)";
+ return false;
+ }
+ if(!fm->format_block) {
+ if(error) *error = "invalid Wave64 file: \"data\" chunk before \"fmt \" chunk (008)";
+ return false;
+ }
+ fm->audio_block = fm->num_blocks;
+ }
+ if(!append_block_(fm, offset, memcmp(buffer, "\x64\x61\x74\x61\xF3\xAC\xD3\x11\x8C\xD1\x00\xC0\x4F\x8E\xDB\x8A", 16)? (FLAC__uint32)size : 16+8, error))
+ return false;
+ /* skip to next chunk */
+ if(fseeko(f, size-24, SEEK_CUR) < 0) {
+ if(error) *error = "invalid Wave64 file: seek error (009)";
+ return false;
+ }
+ }
+ if(eof_offset != ftello(f)) {
+ if(error) *error = "invalid Wave64 file: unexpected EOF (010)";
+ return false;
+ }
+ if(!fm->format_block) {
+ if(error) *error = "invalid Wave64 file: missing \"fmt \" chunk (011)";
+ return false;
+ }
+ if(!fm->audio_block) {
+ if(error) *error = "invalid Wave64 file: missing \"data\" chunk (012)";
+ return false;
+ }
+ return true;
+}
+