| ... | ... | @@ -1789,12 +1789,9 @@ test { |
| 1789 | 1789 | _ = UnpackResult; |
| 1790 | 1790 | } |
| 1791 | 1791 | |
| 1792 | | // Detects executable header: ELF magic header or shebang line. |
| 1792 | // Detects executable header: ELF or Macho-O magic header or shebang line. |
| 1793 | 1793 | const FileHeader = struct { |
| 1794 | | const elf_magic = std.elf.MAGIC; |
| 1795 | | const shebang = "#!"; |
| 1796 | | |
| 1797 | | header: [@max(elf_magic.len, shebang.len)]u8 = undefined, |
| 1794 | header: [4]u8 = undefined, |
| 1798 | 1795 | bytes_read: usize = 0, |
| 1799 | 1796 | |
| 1800 | 1797 | pub fn update(self: *FileHeader, buf: []const u8) void { |
| ... | ... | @@ -1804,9 +1801,27 @@ const FileHeader = struct { |
| 1804 | 1801 | self.bytes_read += n; |
| 1805 | 1802 | } |
| 1806 | 1803 | |
| 1804 | fn isScript(self: *FileHeader) bool { |
| 1805 | const shebang = "#!"; |
| 1806 | return std.mem.eql(u8, self.header[0..@min(self.bytes_read, shebang.len)], shebang); |
| 1807 | } |
| 1808 | |
| 1809 | fn isElf(self: *FileHeader) bool { |
| 1810 | const elf_magic = std.elf.MAGIC; |
| 1811 | return std.mem.eql(u8, self.header[0..@min(self.bytes_read, elf_magic.len)], elf_magic); |
| 1812 | } |
| 1813 | |
| 1814 | fn isMachO(self: *FileHeader) bool { |
| 1815 | if (self.bytes_read < 4) return false; |
| 1816 | const magic_number = std.mem.readInt(u32, &self.header, builtin.cpu.arch.endian()); |
| 1817 | return magic_number == std.macho.MH_MAGIC or |
| 1818 | magic_number == std.macho.MH_MAGIC_64 or |
| 1819 | magic_number == std.macho.FAT_MAGIC or |
| 1820 | magic_number == std.macho.FAT_MAGIC_64; |
| 1821 | } |
| 1822 | |
| 1807 | 1823 | pub fn isExecutable(self: *FileHeader) bool { |
| 1808 | | return std.mem.eql(u8, self.header[0..@min(self.bytes_read, shebang.len)], shebang) or |
| 1809 | | std.mem.eql(u8, self.header[0..@min(self.bytes_read, elf_magic.len)], elf_magic); |
| 1824 | return self.isScript() or self.isElf() or self.isMachO(); |
| 1810 | 1825 | } |
| 1811 | 1826 | }; |
| 1812 | 1827 | |
| ... | ... | @@ -1814,12 +1829,18 @@ test FileHeader { |
| 1814 | 1829 | var h: FileHeader = .{}; |
| 1815 | 1830 | try std.testing.expect(!h.isExecutable()); |
| 1816 | 1831 | |
| 1817 | | h.update(FileHeader.elf_magic[0..2]); |
| 1832 | const elf_magic = std.elf.MAGIC; |
| 1833 | h.update(elf_magic[0..2]); |
| 1818 | 1834 | try std.testing.expect(!h.isExecutable()); |
| 1819 | | h.update(FileHeader.elf_magic[2..4]); |
| 1835 | h.update(elf_magic[2..4]); |
| 1836 | try std.testing.expect(h.isExecutable()); |
| 1837 | |
| 1838 | h.update(elf_magic[2..4]); |
| 1820 | 1839 | try std.testing.expect(h.isExecutable()); |
| 1821 | 1840 | |
| 1822 | | h.update(FileHeader.elf_magic[2..4]); |
| 1841 | const macho64_magic_bytes = [_]u8{ 0xCF, 0xFA, 0xED, 0xFE }; |
| 1842 | h.bytes_read = 0; |
| 1843 | h.update(&macho64_magic_bytes); |
| 1823 | 1844 | try std.testing.expect(h.isExecutable()); |
| 1824 | 1845 | } |
| 1825 | 1846 | |