LyoqCiAqIEBmaWxlIG9wX2JmZC5jcHAKICogRW5jYXBzdWxhdGlvbiBvZiBiZmQgb2JqZWN0cwogKgogKiBAcmVtYXJrIENvcHlyaWdodCAyMDAyIE9Qcm9maWxlIGF1dGhvcnMKICogQHJlbWFyayBSZWFkIHRoZSBmaWxlIENPUFlJTkcKICoKICogQGF1dGhvciBQaGlsaXBwZSBFbGllCiAqIEBhdXRob3IgSm9obiBMZXZvbgogKi8KCiNpbmNsdWRlICJvcF9maWxlLmgiCiNpbmNsdWRlICJvcF9jb25maWcuaCIKI2luY2x1ZGUgImNvbmZpZy5oIgoKI2luY2x1ZGUgPGZjbnRsLmg+CiNpbmNsdWRlIDxjc3RyaW5nPgoKI2luY2x1ZGUgPHN5cy9zdGF0Lmg+CgojaW5jbHVkZSA8Y3N0ZGxpYj4KCiNpbmNsdWRlIDxhbGdvcml0aG0+CiNpbmNsdWRlIDxpb3N0cmVhbT4KI2luY2x1ZGUgPGlvbWFuaXA+CiNpbmNsdWRlIDxzc3RyZWFtPgoKI2luY2x1ZGUgIm9wX2JmZC5oIgojaW5jbHVkZSAibG9jYXRlX2ltYWdlcy5oIgojaW5jbHVkZSAic3RyaW5nX2ZpbHRlci5oIgojaW5jbHVkZSAic3RyZWFtX3V0aWwuaCIKI2luY2x1ZGUgImN2ZXJiLmgiCgp1c2luZyBuYW1lc3BhY2Ugc3RkOwoKCnZlcmJvc2UgdmJmZCgiYmZkIik7CgoKbmFtZXNwYWNlIHsKCi8vLyBmdW5jdGlvbiBvYmplY3QgZm9yIGZpbHRlcmluZyBzeW1ib2xzIHRvIHJlbW92ZQpzdHJ1Y3QgcmVtb3ZlX2ZpbHRlciB7CglyZW1vdmVfZmlsdGVyKHN0cmluZ19maWx0ZXIgY29uc3QgJiBmaWx0ZXIpCgkJOiBmaWx0ZXJfKGZpbHRlcikge30KCglib29sIG9wZXJhdG9yKCkob3BfYmZkX3N5bWJvbCBjb25zdCAmIHN5bWJvbCkgewoJCXJldHVybiAhZmlsdGVyXy5tYXRjaChzeW1ib2wubmFtZSgpKTsKCX0KCglzdHJpbmdfZmlsdGVyIGZpbHRlcl87Cn07CgoKfSAvLyBuYW1lc3BhY2UgYW5vbgoKCm9wX2JmZF9zeW1ib2w6Om9wX2JmZF9zeW1ib2woYXN5bWJvbCBjb25zdCAqIGEpCgk6IGJmZF9zeW1ib2woYSksIHN5bWJfdmFsdWUoYS0+dmFsdWUpLAoJICBzZWN0aW9uX2ZpbGVwb3MoYS0+c2VjdGlvbi0+ZmlsZXBvcyksCgkgIHNlY3Rpb25fdm1hKGEtPnNlY3Rpb24tPnZtYSksCgkgIHN5bWJfc2l6ZSgwKSwgc3ltYl9oaWRkZW4oZmFsc2UpLCBzeW1iX3dlYWsoZmFsc2UpLAoJICBzeW1iX2FydGlmaWNpYWwoZmFsc2UpCnsKCS8vIFNvbWUgc2VjdGlvbnMgaGF2ZSB1bm5hbWVkIHN5bWJvbHMgaW4gdGhlbS4gSWYKCS8vIHdlIGp1c3QgaWdub3JlIHRoZW0gdGhlbiB3ZSBlbmQgdXAgc3RpY2tpbmcKCS8vIHRoaW5ncyBsaWtlIC5wbHQgaGl0cyBpbnNpZGUgb2YgX2luaXQuIFNvIGluc3RlYWQKCS8vIHdlIG5hbWUgdGhlIHN5bWJvbCBhZnRlciB0aGUgc2VjdGlvbi4KCWlmIChhLT5uYW1lICYmIGEtPm5hbWVbMF0gIT0gJ1wwJykgewoJCXN5bWJfbmFtZSA9IGEtPm5hbWU7CgkJc3ltYl93ZWFrID0gYS0+ZmxhZ3MgJiBCU0ZfV0VBSzsKCQlzeW1iX2hpZGRlbiA9IChhLT5mbGFncyAmIEJTRl9MT0NBTCkKIAkJCSYmICEoYS0+ZmxhZ3MgJiBCU0ZfR0xPQkFMKTsKCX0gZWxzZSB7CgkJc3ltYl9uYW1lID0gc3RyaW5nKCI/PyIpICsgYS0+c2VjdGlvbi0+bmFtZTsKCX0KfQoKCm9wX2JmZF9zeW1ib2w6Om9wX2JmZF9zeW1ib2woYmZkX3ZtYSB2bWEsIHNpemVfdCBzaXplLCBzdHJpbmcgY29uc3QgJiBuYW1lKQoJOiBiZmRfc3ltYm9sKDApLCBzeW1iX3ZhbHVlKHZtYSksCgkgIHNlY3Rpb25fZmlsZXBvcygwKSwgc2VjdGlvbl92bWEoMCksCgkgIHN5bWJfc2l6ZShzaXplKSwgc3ltYl9uYW1lKG5hbWUpLAoJICBzeW1iX2FydGlmaWNpYWwodHJ1ZSkKewp9CgoKYm9vbCBvcF9iZmRfc3ltYm9sOjpvcGVyYXRvcjwob3BfYmZkX3N5bWJvbCBjb25zdCAmIHJocykgY29uc3QKewoJcmV0dXJuIGZpbGVwb3MoKSA8IHJocy5maWxlcG9zKCk7Cn0KCnVuc2lnbmVkIGxvbmcgb3BfYmZkX3N5bWJvbDo6c3ltYm9sX2VuZHBvcyh2b2lkKSBjb25zdAp7CglyZXR1cm4gYmZkX3N5bWJvbC0+c2VjdGlvbi0+ZmlsZXBvcyArIGJmZF9zeW1ib2wtPnNlY3Rpb24tPnNpemU7Cn0KCgpvcF9iZmQ6Om9wX2JmZChzdHJpbmcgY29uc3QgJiBmbmFtZSwgc3RyaW5nX2ZpbHRlciBjb25zdCAmIHN5bWJvbF9maWx0ZXIsCgkgICAgICAgZXh0cmFfaW1hZ2VzIGNvbnN0ICYgZXh0cmFfaW1hZ2VzLCBib29sICYgb2spCgk6CglmaWxlbmFtZShmbmFtZSksCglhcmNoaXZlX3BhdGgoZXh0cmFfaW1hZ2VzLmdldF9hcmNoaXZlX3BhdGgoKSksCglleHRyYV9mb3VuZF9pbWFnZXMoZXh0cmFfaW1hZ2VzKSwKCWZpbGVfc2l6ZSgtMSksCglhbm9uX29iaihmYWxzZSkKewoJaW50IGZkOwoJc3RydWN0IHN0YXQgc3Q7CgkvLyBhZnRlciBjcmVhdGluZyBhbGwgc3ltYm9sIGl0J3MgY29udmVuaWVudCBmb3IgdXNlciBjb2RlIHRvIGFjY2VzcwoJLy8gc3ltYm9scyB0aHJvdWdoIGEgdmVjdG9yLiBXZSB1c2UgYW4gaW50ZXJtZWRpYXRlIGxpc3QgdG8gYXZvaWQgYQoJLy8gTyhOsikgYmVoYXZpb3Igd2hlbiB3ZSB3aWxsIGZpbHRlciB2ZWN0b3IgZWxlbWVudCBiZWxvdwoJc3ltYm9sc19mb3VuZF90IHN5bWJvbHM7Cglhc2VjdGlvbiBjb25zdCAqIHNlY3Q7CglzdHJpbmcgc3VmID0gIi5qbyI7CgoJaW1hZ2VfZXJyb3IgaW1nX29rOwoJc3RyaW5nIGNvbnN0IGltYWdlX3BhdGggPQoJCWV4dHJhX2ltYWdlcy5maW5kX2ltYWdlX3BhdGgoZmlsZW5hbWUsIGltZ19vaywgdHJ1ZSk7CgoJY3ZlcmIgPDwgdmJmZCA8PCAib3BfYmZkIGN0b3IgZm9yICIgPDwgaW1hZ2VfcGF0aCA8PCBlbmRsOwoKCS8vIGlmIHRoZXJlJ3MgYSBwcm9ibGVtIGFscmVhZHksIGRvbid0IHRyeSB0byBvcGVuIGl0CglpZiAoIW9rIHx8IGltZ19vayAhPSBpbWFnZV9vaykgewoJCWN2ZXJiIDw8IHZiZmQgPDwgImNhbid0IGxvY2F0ZSAiIDw8IGltYWdlX3BhdGggPDwgZW5kbDsKCQlnb3RvIG91dF9mYWlsOwoJfQoKCWZkID0gb3BlbihpbWFnZV9wYXRoLmNfc3RyKCksIE9fUkRPTkxZKTsKCWlmIChmZCA9PSAtMSkgewoJCWN2ZXJiIDw8IHZiZmQgPDwgIm9wZW4gZmFpbGVkIGZvciAiIDw8IGltYWdlX3BhdGggPDwgZW5kbDsKCQlvayA9IGZhbHNlOwoJCWdvdG8gb3V0X2ZhaWw7Cgl9CgoJaWYgKGZzdGF0KGZkLCAmc3QpKSB7CgkJY3ZlcmIgPDwgdmJmZCA8PCAic3RhdCBmYWlsZWQgZm9yICIgPDwgaW1hZ2VfcGF0aCA8PCBlbmRsOwoJCW9rID0gZmFsc2U7CgkJZ290byBvdXRfZmFpbDsKCX0KCglmaWxlX3NpemUgPSBzdC5zdF9zaXplOwoKCWliZmQuYWJmZCA9IGZkb3Blbl9iZmQoaW1hZ2VfcGF0aCwgZmQpOwoKCWlmICghaWJmZC52YWxpZCgpKSB7CgkJY3ZlcmIgPDwgdmJmZCA8PCAiZmRvcGVuX2JmZCBmYWlsZWQgZm9yICIgPDwgaW1hZ2VfcGF0aCA8PCBlbmRsOwoJCW9rID0gZmFsc2U7CgkJZ290byBvdXRfZmFpbDsKCX0KCglzdHJpbmc6OnNpemVfdHlwZSBwb3M7Cglwb3MgPSBmaWxlbmFtZS5yZmluZChzdWYpOwoJaWYgKHBvcyAhPSBzdHJpbmc6Om5wb3MgJiYgcG9zID09IGZpbGVuYW1lLnNpemUoKSAtIHN1Zi5zaXplKCkpCgkJYW5vbl9vYmogPSB0cnVlOwoKCgkvLyBmaW5kIC50ZXh0IGFuZCB1c2UgaXQKCWZvciAoc2VjdCA9IGliZmQuYWJmZC0+c2VjdGlvbnM7IHNlY3Q7IHNlY3QgPSBzZWN0LT5uZXh0KSB7CgkJaWYgKHNlY3QtPmZsYWdzICYgU0VDX0NPREUpIHsKCQkJaWYgKGZpbGVwb3NfbWFwW3NlY3QtPm5hbWVdICE9IDApIHsKCQkJCWNlcnIgPDwgIkZvdW5kIHNlY3Rpb24gXCIiIDw8IHNlY3QtPm5hbWUKCQkJCSAgICAgPDwgIlwiIHR3aWNlIGZvciAiIDw8IGdldF9maWxlbmFtZSgpCgkJCQkgICAgIDw8IGVuZGw7CgkJCQlhYm9ydCgpOwoJCQl9CgoJCQlmaWxlcG9zX21hcFtzZWN0LT5uYW1lXSA9IHNlY3QtPmZpbGVwb3M7CgoJCQlpZiAoc2VjdC0+dm1hID09IDAgJiYgc3RyY21wKHNlY3QtPm5hbWUsICIudGV4dCIpKQoJCQkJZmlsdGVyZWRfc2VjdGlvbi5wdXNoX2JhY2soc2VjdCk7CgkJfQoJfQoKCWdldF9zeW1ib2xzKHN5bWJvbHMpOwoKb3V0OgoJYWRkX3N5bWJvbHMoc3ltYm9scywgc3ltYm9sX2ZpbHRlcik7CglyZXR1cm47Cm91dF9mYWlsOgoJaWJmZC5jbG9zZSgpOwoJZGJmZC5jbG9zZSgpOwoJLy8gbWFrZSB0aGUgZmFrZSBzeW1ib2wgZml0IHdpdGhpbiB0aGUgZmFrZSBmaWxlCglmaWxlX3NpemUgPSAtMTsKCWdvdG8gb3V0Owp9CgoKb3BfYmZkOjp+b3BfYmZkKCkKewp9CgoKdW5zaWduZWQgbG9uZyBvcF9iZmQ6OmdldF9zdGFydF9vZmZzZXQoYmZkX3ZtYSB2bWEpIGNvbnN0CnsKCWlmICghdm1hIHx8ICFpYmZkLnZhbGlkKCkpIHsKCQlmaWxlcG9zX21hcF90Ojpjb25zdF9pdGVyYXRvciBpdCA9IGZpbGVwb3NfbWFwLmZpbmQoIi50ZXh0Iik7CgkJaWYgKGl0ICE9IGZpbGVwb3NfbWFwLmVuZCgpKQoJCQlyZXR1cm4gaXQtPnNlY29uZDsKCQlyZXR1cm4gMDsKCX0KCglyZXR1cm4gMDsKfQoKCnZvaWQgb3BfYmZkOjpnZXRfc3ltYm9scyhvcF9iZmQ6OnN5bWJvbHNfZm91bmRfdCAmIHN5bWJvbHMpCnsKCWliZmQuZ2V0X3N5bWJvbHMoKTsKCgkvLyBPbiBzZXBhcmF0ZSBkZWJ1ZyBmaWxlIHN5c3RlbXMsIHRoZSBtYWluIGJmZCBoYXMgbm8gc3ltYm9scywKCS8vIHNvIGV2ZW4gZm9yIG5vbiAtZyByZXBvcnRzLCB3ZSB3YW50IHRvIHByb2Nlc3MgdGhlIGRiZmQuCgkvLyBUaGlzIGh1cnRzIHVzIHByZXR0eSBiYWRseSAodGhlIENSQyksIGJ1dCB3ZSByZWFsbHkgZG9uJ3QKCS8vIGhhdmUgbXVjaCBjaG9pY2UgYXQgdGhlIG1vbWVudC4KCWhhc19kZWJ1Z19pbmZvKCk7CgoJZGJmZC5zZXRfaW1hZ2VfYmZkX2luZm8oJmliZmQpOwoJZGJmZC5nZXRfc3ltYm9scygpOwoKCXNpemVfdCBpOwoJZm9yIChpID0gMDsgaSA8IGliZmQubnJfc3ltczsgKytpKSB7CgkJaWYgKCFpbnRlcmVzdGluZ19zeW1ib2woaWJmZC5zeW1zW2ldKSkKCQkJY29udGludWU7CgkJaWYgKGZpbmQoZmlsdGVyZWRfc2VjdGlvbi5iZWdpbigpLCBmaWx0ZXJlZF9zZWN0aW9uLmVuZCgpLAoJCQkgaWJmZC5zeW1zW2ldLT5zZWN0aW9uKSAhPSBmaWx0ZXJlZF9zZWN0aW9uLmVuZCgpKQoJCQljb250aW51ZTsKCQlzeW1ib2xzLnB1c2hfYmFjayhvcF9iZmRfc3ltYm9sKGliZmQuc3ltc1tpXSkpOwoJfQoKCWZvciAoaSA9IDA7IGkgPCBkYmZkLm5yX3N5bXM7ICsraSkgewoJCWlmICghaW50ZXJlc3Rpbmdfc3ltYm9sKGRiZmQuc3ltc1tpXSkpCgkJCWNvbnRpbnVlOwoKCQkvLyBuZWVkIHRvIHVzZSBmaWxlcG9zIG9mIG9yaWdpbmFsIGZpbGUncyBzZWN0aW9uIGZvcgoJCS8vIGRlYnVnIGZpbGUgc3ltYm9scy4gV2UgcHJvYmFibHkgbmVlZCB0byBiZSBtb3JlCgkJLy8gY2FyZWZ1bCBmb3Igc3BlY2lhbCBzeW1ib2xzIHdoaWNoIGhhdmUgLT5zZWN0aW9uIGZyb20KCQkvLyAucm9kYXRhIGxpa2UgKkFCUyoKCQl1MzIgZmlsZXBvcyA9IGZpbGVwb3NfbWFwW2RiZmQuc3ltc1tpXS0+c2VjdGlvbi0+bmFtZV07CgkJaWYgKGZpbGVwb3MgIT0gMCkKCQkJZGJmZC5zeW1zW2ldLT5zZWN0aW9uLT5maWxlcG9zID0gZmlsZXBvczsKCQlzeW1ib2xzLnB1c2hfYmFjayhvcF9iZmRfc3ltYm9sKGRiZmQuc3ltc1tpXSkpOwoJfQoKCXN5bWJvbHMuc29ydCgpOwoKCXN5bWJvbHNfZm91bmRfdDo6aXRlcmF0b3IgaXQgPSBzeW1ib2xzLmJlZ2luKCk7CgoJLy8gd2UgbmVlZCB0byBlbnN1cmUgdGhhbiBmb3IgYSBnaXZlbiB2bWEgb25seSBvbmUgc3ltYm9sIGV4aXN0IGVsc2UKCS8vIHdlIHJlYWQgbW9yZSB0aGFuIG9uZSB0aW1lIHNvbWUgc2FtcGxlcy4gRml4ICM1MjYwOTgKCXdoaWxlIChpdCAhPSBzeW1ib2xzLmVuZCgpKSB7CgkJc3ltYm9sc19mb3VuZF90OjppdGVyYXRvciB0ZW1wID0gaXQ7CgkJKyt0ZW1wOwoJCWlmICh0ZW1wICE9IHN5bWJvbHMuZW5kKCkgJiYgKGl0LT52bWEoKSA9PSB0ZW1wLT52bWEoKSkgJiYKCQkJKGl0LT5maWxlcG9zKCkgPT0gdGVtcC0+ZmlsZXBvcygpKSkgewoJCQlpZiAoYm9yaW5nX3N5bWJvbCgqaXQsICp0ZW1wKSkgewoJCQkJaXQgPSBzeW1ib2xzLmVyYXNlKGl0KTsKCQkJfSBlbHNlIHsKCQkJCXN5bWJvbHMuZXJhc2UodGVtcCk7CgkJCX0KCQl9IGVsc2UgewoJCQkrK2l0OwoJCX0KCX0KCgkvLyBub3cgd2UgY2FuIGNhbGN1bGF0ZSB0aGUgc3ltYm9sIHNpemUsIHdlIGNhbid0IGZpcnN0IGluY2x1ZGUvZXhjbHVkZQoJLy8gc3ltYm9scyBiZWNhdXNlIHRoZSBzaXplIG9mIHN5bWJvbCBpcyBjYWxjdWxhdGVkIGZyb20gdGhlIGRpZmZlcmVuY2UKCS8vIGJldHdlZW4gdGhlIHZtYSBvZiBhIHN5bWJvbCBhbmQgdGhlIG5leHQgb25lLgoJZm9yIChpdCA9IHN5bWJvbHMuYmVnaW4oKSA7IGl0ICE9IHN5bWJvbHMuZW5kKCk7ICsraXQpIHsKCQlvcF9iZmRfc3ltYm9sIGNvbnN0ICogbmV4dCA9IDA7CgkJc3ltYm9sc19mb3VuZF90OjppdGVyYXRvciB0ZW1wID0gaXQ7CgkJKyt0ZW1wOwoJCWlmICh0ZW1wICE9IHN5bWJvbHMuZW5kKCkpCgkJCW5leHQgPSAmKnRlbXA7CgkJaXQtPnNpemUoc3ltYm9sX3NpemUoKml0LCBuZXh0KSk7Cgl9Cn0KCgp2b2lkIG9wX2JmZDo6YWRkX3N5bWJvbHMob3BfYmZkOjpzeW1ib2xzX2ZvdW5kX3QgJiBzeW1ib2xzLAogICAgICAgICAgICAgICAgICAgICAgICAgc3RyaW5nX2ZpbHRlciBjb25zdCAmIHN5bWJvbF9maWx0ZXIpCnsKCS8vIGltYWdlcyB3aXRoIG5vIHN5bWJvbHMgZGVidWcgaW5mbyBhdmFpbGFibGUgZ2V0IGEgcGxhY2Vob2xkZXIgc3ltYm9sCglpZiAoc3ltYm9scy5lbXB0eSgpKQoJCXN5bWJvbHMucHVzaF9iYWNrKGNyZWF0ZV9hcnRpZmljaWFsX3N5bWJvbCgpKTsKCgljdmVyYiA8PCB2YmZkIDw8ICJudW1iZXIgb2Ygc3ltYm9scyBiZWZvcmUgZmlsdGVyaW5nICIKCSAgICAgIDw8IGRlYyA8PCBzeW1ib2xzLnNpemUoKSA8PCBoZXggPDwgZW5kbDsKCglzeW1ib2xzX2ZvdW5kX3Q6Oml0ZXJhdG9yIGl0OwoJaXQgPSByZW1vdmVfaWYoc3ltYm9scy5iZWdpbigpLCBzeW1ib2xzLmVuZCgpLAoJICAgICAgICAgICAgICAgcmVtb3ZlX2ZpbHRlcihzeW1ib2xfZmlsdGVyKSk7CgoJY29weShzeW1ib2xzLmJlZ2luKCksIGl0LCBiYWNrX2luc2VydGVyKHN5bXMpKTsKCgljdmVyYiA8PCB2YmZkIDw8ICJudW1iZXIgb2Ygc3ltYm9scyBub3cgIgoJICAgICAgPDwgZGVjIDw8IHN5bXMuc2l6ZSgpIDw8IGhleCA8PCBlbmRsOwp9CgoKYmZkX3ZtYSBvcF9iZmQ6Om9mZnNldF90b19wYyhiZmRfdm1hIG9mZnNldCkgY29uc3QKewoJYXNlY3Rpb24gY29uc3QgKiBzZWN0ID0gaWJmZC5hYmZkLT5zZWN0aW9uczsKCglmb3IgKDsgc2VjdDsgc2VjdCA9IHNlY3QtPm5leHQpIHsKCQlpZiAob2Zmc2V0ID49IGJmZF92bWEoc2VjdC0+ZmlsZXBvcykgJiYKCQkgICAgKCFzZWN0LT5uZXh0IHx8IG9mZnNldCA8IGJmZF92bWEoc2VjdC0+bmV4dC0+ZmlsZXBvcykpKSB7CgkJCXJldHVybiBzZWN0LT52bWEgKyAob2Zmc2V0IC0gc2VjdC0+ZmlsZXBvcyk7CgkJfQoJfQoKCXJldHVybiAwOwp9Cgpib29sIG9wX2JmZDo6CnN5bWJvbF9oYXNfY29udGVudHMoc3ltYm9sX2luZGV4X3Qgc3ltX2lkeCkKewoJb3BfYmZkX3N5bWJvbCBjb25zdCAmIGJmZF9zeW0gPSBzeW1zW3N5bV9pZHhdOwoJc3RyaW5nIGNvbnN0IG5hbWUgPSBiZmRfc3ltLm5hbWUoKTsKCWlmIChuYW1lLnNpemUoKSA9PSAwIHx8IGJmZF9zeW0uYXJ0aWZpY2lhbCgpIHx8ICFpYmZkLnZhbGlkKCkpCgkJcmV0dXJuIGZhbHNlOwoJZWxzZQoJCXJldHVybiB0cnVlOwp9Cgpib29sIG9wX2JmZDo6CmdldF9zeW1ib2xfY29udGVudHMoc3ltYm9sX2luZGV4X3Qgc3ltX2luZGV4LCB1bnNpZ25lZCBjaGFyICogY29udGVudHMpIGNvbnN0CnsKCW9wX2JmZF9zeW1ib2wgY29uc3QgJiBiZmRfc3ltID0gc3ltc1tzeW1faW5kZXhdOwoJc2l6ZV90IHNpemUgPSBiZmRfc3ltLnNpemUoKTsKCglpZiAoIWJmZF9nZXRfc2VjdGlvbl9jb250ZW50cyhpYmZkLmFiZmQsIGJmZF9zeW0uc3ltYm9sKCktPnNlY3Rpb24sIAoJCQkJIGNvbnRlbnRzLCAKCQkJCSBzdGF0aWNfY2FzdDxmaWxlX3B0cj4oYmZkX3N5bS52YWx1ZSgpKSwgc2l6ZSkpIHsKCQlyZXR1cm4gZmFsc2U7Cgl9CglyZXR1cm4gdHJ1ZTsKfQoKYm9vbCBvcF9iZmQ6Omhhc19kZWJ1Z19pbmZvKCkgY29uc3QKewoJaWYgKGRlYnVnX2luZm8uY2FjaGVkKCkpCgkJcmV0dXJuIGRlYnVnX2luZm8uZ2V0KCk7CgoJaWYgKCFpYmZkLnZhbGlkKCkpCgkJcmV0dXJuIGRlYnVnX2luZm8ucmVzZXQoZmFsc2UpOwoKCWlmIChpYmZkLmhhc19kZWJ1Z19pbmZvKCkpCgkJcmV0dXJuIGRlYnVnX2luZm8ucmVzZXQodHJ1ZSk7CgoJLy8gY2hlY2sgdG8gc2VlIGlmIHRoZXJlIGlzIGFuIC5kZWJ1ZyBmaWxlCgoJaWYgKGZpbmRfc2VwYXJhdGVfZGVidWdfZmlsZShpYmZkLmFiZmQsIGZpbGVuYW1lLCBkZWJ1Z19maWxlbmFtZSwgZXh0cmFfZm91bmRfaW1hZ2VzKSkgewoJCWN2ZXJiIDw8IHZiZmQgPDwgIm5vdyBsb2FkaW5nOiAiIDw8IGRlYnVnX2ZpbGVuYW1lIDw8IGVuZGw7CgkJZGJmZC5hYmZkID0gb3Blbl9iZmQoZGVidWdfZmlsZW5hbWUpOwoJCWlmIChkYmZkLmhhc19kZWJ1Z19pbmZvKCkpCgkJCXJldHVybiBkZWJ1Z19pbmZvLnJlc2V0KHRydWUpOwoJfQoKCS8vIC5kZWJ1ZyBpcyBvcHRpb25hbCwgc28gd2lsbCBub3QgZmFpbCBpZiB0aGVyZSdzIGEgcHJvYmxlbQoJY3ZlcmIgPDwgdmJmZCA8PCAiZmFpbGVkIHRvIHByb2Nlc3Mgc2VwYXJhdGUgZGVidWcgZmlsZSAiCgkgICAgICA8PCBkZWJ1Z19maWxlbmFtZSA8PCBlbmRsOwoKCXJldHVybiBkZWJ1Z19pbmZvLnJlc2V0KGZhbHNlKTsKfQoKCmJvb2wgb3BfYmZkOjpnZXRfbGluZW5yKHN5bWJvbF9pbmRleF90IHN5bV9pZHgsIGJmZF92bWEgb2Zmc2V0LAoJCQlzdHJpbmcgJiBzb3VyY2VfZmlsZW5hbWUsIHVuc2lnbmVkIGludCAmIGxpbmVucikgY29uc3QKewoJaWYgKCFoYXNfZGVidWdfaW5mbygpKQoJCXJldHVybiBmYWxzZTsKCgliZmRfaW5mbyBjb25zdCAmIGIgPSBkYmZkLnZhbGlkKCkgPyBkYmZkIDogaWJmZDsKCW9wX2JmZF9zeW1ib2wgY29uc3QgJiBzeW0gPSBzeW1zW3N5bV9pZHhdOwoKCWxpbmVucl9pbmZvIGNvbnN0IGluZm8gPSBmaW5kX25lYXJlc3RfbGluZShiLCBzeW0sIG9mZnNldCwgYW5vbl9vYmopOwoKCWlmICghaW5mby5mb3VuZCkKCQlyZXR1cm4gZmFsc2U7CgoJc291cmNlX2ZpbGVuYW1lID0gaW5mby5maWxlbmFtZTsKCWxpbmVuciA9IGluZm8ubGluZTsKCXJldHVybiB0cnVlOwp9CgoKc2l6ZV90IG9wX2JmZDo6c3ltYm9sX3NpemUob3BfYmZkX3N5bWJvbCBjb25zdCAmIHN5bSwKCQkJICAgb3BfYmZkX3N5bWJvbCBjb25zdCAqIG5leHQpIGNvbnN0CnsKCXVuc2lnbmVkIGxvbmcgbG9uZyBzdGFydCA9IHN5bS5maWxlcG9zKCk7Cgl1bnNpZ25lZCBsb25nIGxvbmcgZW5kOwoKCWlmIChuZXh0ICYmIChzeW0uc2VjdGlvbigpICE9IG5leHQtPnNlY3Rpb24oKSkpCgkJZW5kID0gc3ltLnN5bWJvbF9lbmRwb3MoKTsKCWVsc2UKCQllbmQgPSBuZXh0ID8gbmV4dC0+ZmlsZXBvcygpIDogZmlsZV9zaXplOwoKCWlmIChzdGFydCA+IGVuZCkKCQlyZXR1cm4gMDsKCglyZXR1cm4gZW5kIC0gc3RhcnQ7Cn0KCgp2b2lkIG9wX2JmZDo6Z2V0X3N5bWJvbF9yYW5nZShzeW1ib2xfaW5kZXhfdCBzeW1faWR4LAoJCQkgICAgICB1bnNpZ25lZCBsb25nIGxvbmcgJiBzdGFydCwgdW5zaWduZWQgbG9uZyBsb25nICYgZW5kKSBjb25zdAp7CglvcF9iZmRfc3ltYm9sIGNvbnN0ICYgc3ltID0gc3ltc1tzeW1faWR4XTsKCglib29sIGNvbnN0IHZlcmJvc2UgPSBjdmVyYiA8PCAodmJmZCAmIHZsZXZlbDEpOwoKCWlmIChhbm9uX29iaikKCQlzdGFydCA9IHN5bS52bWEoKTsKCWVsc2UKCQlzdGFydCA9IHN5bS5maWxlcG9zKCk7CgllbmQgPSBzdGFydCArIHN5bS5zaXplKCk7CgoJaWYgKCF2ZXJib3NlKQoJCXJldHVybjsKCglpb19zdGF0ZSBzdGF0ZShjdmVyYiA8PCAodmJmZCAmIHZsZXZlbDEpKTsKCgljdmVyYiA8PCAodmJmZCAmIHZsZXZlbDEpIDw8ICJzeW1ib2wgIiA8PCBzeW0ubmFtZSgpCgkgICAgICA8PCAiLCB2YWx1ZSAiIDw8IGhleCA8PCBzeW0udmFsdWUoKSA8PCBlbmRsOwoJY3ZlcmIgPDwgKHZiZmQgJiB2bGV2ZWwxKQoJICAgICAgPDwgInN0YXJ0ICIgPDwgaGV4IDw8IHN0YXJ0IDw8ICIsIGVuZCAiIDw8IGVuZCA8PCBlbmRsOwoKCWlmIChzeW0uc3ltYm9sKCkpIHsKCQljdmVyYiA8PCAodmJmZCAmIHZsZXZlbDEpIDw8ICJpbiBzZWN0aW9uICIKCQkgICAgICA8PCBzeW0uc3ltYm9sKCktPnNlY3Rpb24tPm5hbWUgPDwgIiwgZmlsZXBvcyAiCgkJICAgICAgPDwgaGV4IDw8IHN5bS5zeW1ib2woKS0+c2VjdGlvbi0+ZmlsZXBvcyA8PCBlbmRsOwoJfQp9CgoKdm9pZCBvcF9iZmQ6OmdldF92bWFfcmFuZ2UoYmZkX3ZtYSAmIHN0YXJ0LCBiZmRfdm1hICYgZW5kKSBjb25zdAp7CglpZiAoIXN5bXMuZW1wdHkoKSkgewoJCS8vIHN5bXMgYXJlIHNvcnRlZCBieSB2bWEgc28gdm1hIG9mIHRoZSBmaXJzdCBzeW1ib2wgYW5kIHZtYSArCgkJLy8gc2l6ZSBvZiB0aGUgbGFzdCBzeW1ib2wgZ2l2ZSB0aGUgdm1hIHJhbmdlIGZvciBncHJvZiBvdXRwdXQKCQlvcF9iZmRfc3ltYm9sIGNvbnN0ICYgbGFzdF9zeW1iID0gc3ltc1tzeW1zLnNpemUoKSAtIDFdOwoJCXN0YXJ0ID0gc3ltc1swXS52bWEoKTsKCQkvLyBlbmQgaXMgZXhjbHVkZWQgZnJvbSByYW5nZSBzbyArIDEgKmlmKiBsYXN0X3N5bWIuc2l6ZSgpICE9IDAKCQllbmQgPSBsYXN0X3N5bWIudm1hKCkgKyBsYXN0X3N5bWIuc2l6ZSgpICsgKGxhc3Rfc3ltYi5zaXplKCkgIT0gMCk7Cgl9IGVsc2UgewoJCXN0YXJ0ID0gMDsKCQllbmQgPSBmaWxlX3NpemU7Cgl9Cn0KCgpvcF9iZmRfc3ltYm9sIGNvbnN0IG9wX2JmZDo6Y3JlYXRlX2FydGlmaWNpYWxfc3ltYm9sKCkKewoKCWJmZF92bWEgc3RhcnQsIGVuZDsKCWdldF92bWFfcmFuZ2Uoc3RhcnQsIGVuZCk7CglyZXR1cm4gb3BfYmZkX3N5bWJvbChzdGFydCwgZW5kIC0gc3RhcnQsIGdldF9maWxlbmFtZSgpKTsKfQoKCnN0cmluZyBvcF9iZmQ6OmdldF9maWxlbmFtZSgpIGNvbnN0CnsKCXJldHVybiBmaWxlbmFtZTsKfQoKCnNpemVfdCBvcF9iZmQ6OmJmZF9hcmNoX2JpdHNfcGVyX2FkZHJlc3MoKSBjb25zdAp7CglpZiAoaWJmZC52YWxpZCgpKQoJCXJldHVybiA6OmJmZF9hcmNoX2JpdHNfcGVyX2FkZHJlc3MoaWJmZC5hYmZkKTsKCS8vIEZJWE1FOiB0aGlzIGZ1bmN0aW9uIHNob3VsZCBiZSBjYWxsZWQgb25seSBpZiB0aGUgdW5kZXJsaW5lZCBpYmZkCgkvLyBpcyBvaywgbXVzdCB3ZSB0aHJvdyA/CglyZXR1cm4gc2l6ZW9mKGJmZF92bWEpOwp9Cg==