Skip to content

Commit 48cef8d

Browse files
committed
refactor std.zig.system.NativeTargetInfo functions
to make them a bit easier to test.
1 parent c903b76 commit 48cef8d

File tree

1 file changed

+34
-31
lines changed

1 file changed

+34
-31
lines changed

lib/std/zig/system.zig

Lines changed: 34 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -399,17 +399,38 @@ pub const NativeTargetInfo = struct {
399399
return result;
400400
}
401401

402+
const env_file = std.fs.openFileAbsoluteC("/usr/bin/env", .{}) catch |err| switch (err) {
403+
error.NoSpaceLeft => unreachable,
404+
error.NameTooLong => unreachable,
405+
error.PathAlreadyExists => unreachable,
406+
error.SharingViolation => unreachable,
407+
error.InvalidUtf8 => unreachable,
408+
error.BadPathName => unreachable,
409+
error.PipeBusy => unreachable,
410+
411+
error.IsDir,
412+
error.NotDir,
413+
error.AccessDenied,
414+
error.NoDevice,
415+
error.FileNotFound,
416+
error.FileTooBig,
417+
error.Unexpected,
418+
=> return defaultAbiAndDynamicLinker(cpu, os, cross_target),
419+
420+
else => |e| return e,
421+
};
422+
defer env_file.close();
423+
402424
// If Zig is statically linked, such as via distributed binary static builds, the above
403425
// trick won't work. The next thing we fall back to is the same thing, but for /usr/bin/env.
404426
// Since that path is hard-coded into the shebang line of many portable scripts, it's a
405427
// reasonably reliable path to check for.
406-
return abiAndDynamicLinkerFromUsrBinEnv(cpu, os, ld_info_list, cross_target) catch |err| switch (err) {
428+
return abiAndDynamicLinkerFromFile(env_file, cpu, os, ld_info_list, cross_target) catch |err| switch (err) {
407429
error.FileSystem,
408430
error.SystemResources,
409431
error.SymLinkLoop,
410432
error.ProcessFdQuotaExceeded,
411433
error.SystemFdQuotaExceeded,
412-
error.DeviceBusy,
413434
=> |e| return e,
414435

415436
error.UnableToReadElfFile,
@@ -418,7 +439,6 @@ pub const NativeTargetInfo = struct {
418439
error.InvalidElfEndian,
419440
error.InvalidElfFile,
420441
error.InvalidElfMagic,
421-
error.UsrBinEnvNotAvailable,
422442
error.Unexpected,
423443
error.UnexpectedEndOfFile,
424444
error.NameTooLong,
@@ -461,32 +481,15 @@ pub const NativeTargetInfo = struct {
461481
};
462482
}
463483

464-
fn abiAndDynamicLinkerFromUsrBinEnv(
484+
pub fn abiAndDynamicLinkerFromFile(
485+
file: fs.File,
465486
cpu: Target.Cpu,
466487
os: Target.Os,
467488
ld_info_list: []const LdInfo,
468489
cross_target: CrossTarget,
469490
) !NativeTargetInfo {
470-
const env_file = std.fs.openFileAbsoluteC("/usr/bin/env", .{}) catch |err| switch (err) {
471-
error.NoSpaceLeft => unreachable,
472-
error.NameTooLong => unreachable,
473-
error.PathAlreadyExists => unreachable,
474-
error.SharingViolation => unreachable,
475-
error.InvalidUtf8 => unreachable,
476-
error.BadPathName => unreachable,
477-
error.PipeBusy => unreachable,
478-
479-
error.IsDir => return error.UsrBinEnvNotAvailable,
480-
error.NotDir => return error.UsrBinEnvNotAvailable,
481-
error.AccessDenied => return error.UsrBinEnvNotAvailable,
482-
error.NoDevice => return error.UsrBinEnvNotAvailable,
483-
error.FileNotFound => return error.UsrBinEnvNotAvailable,
484-
error.FileTooBig => return error.UsrBinEnvNotAvailable,
485-
486-
else => |e| return e,
487-
};
488491
var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 align(@alignOf(elf.Elf64_Ehdr)) = undefined;
489-
_ = try preadFull(env_file, &hdr_buf, 0, hdr_buf.len);
492+
_ = try preadFull(file, &hdr_buf, 0, hdr_buf.len);
490493
const hdr32 = @ptrCast(*elf.Elf32_Ehdr, &hdr_buf);
491494
const hdr64 = @ptrCast(*elf.Elf64_Ehdr, &hdr_buf);
492495
if (!mem.eql(u8, hdr32.e_ident[0..4], "\x7fELF")) return error.InvalidElfMagic;
@@ -526,7 +529,7 @@ pub const NativeTargetInfo = struct {
526529
// Reserve some bytes so that we can deref the 64-bit struct fields
527530
// even when the ELF file is 32-bits.
528531
const ph_reserve: usize = @sizeOf(elf.Elf64_Phdr) - @sizeOf(elf.Elf32_Phdr);
529-
const ph_read_byte_len = try preadFull(env_file, ph_buf[0 .. ph_buf.len - ph_reserve], phoff, phentsize);
532+
const ph_read_byte_len = try preadFull(file, ph_buf[0 .. ph_buf.len - ph_reserve], phoff, phentsize);
530533
var ph_buf_i: usize = 0;
531534
while (ph_buf_i < ph_read_byte_len and ph_i < phnum) : ({
532535
ph_i += 1;
@@ -541,7 +544,7 @@ pub const NativeTargetInfo = struct {
541544
const p_offset = elfInt(is_64, need_bswap, ph32.p_offset, ph64.p_offset);
542545
const p_filesz = elfInt(is_64, need_bswap, ph32.p_filesz, ph64.p_filesz);
543546
if (p_filesz > result.dynamic_linker.buffer.len) return error.NameTooLong;
544-
_ = try preadFull(env_file, result.dynamic_linker.buffer[0..p_filesz], p_offset, p_filesz);
547+
_ = try preadFull(file, result.dynamic_linker.buffer[0..p_filesz], p_offset, p_filesz);
545548
// PT_INTERP includes a null byte in p_filesz.
546549
const len = p_filesz - 1;
547550
// dynamic_linker.max_byte is "max", not "len".
@@ -573,7 +576,7 @@ pub const NativeTargetInfo = struct {
573576
// even when the ELF file is 32-bits.
574577
const dyn_reserve: usize = @sizeOf(elf.Elf64_Dyn) - @sizeOf(elf.Elf32_Dyn);
575578
const dyn_read_byte_len = try preadFull(
576-
env_file,
579+
file,
577580
dyn_buf[0 .. dyn_buf.len - dyn_reserve],
578581
dyn_off,
579582
dyn_size,
@@ -617,14 +620,14 @@ pub const NativeTargetInfo = struct {
617620
var sh_buf: [16 * @sizeOf(elf.Elf64_Shdr)]u8 align(@alignOf(elf.Elf64_Shdr)) = undefined;
618621
if (sh_buf.len < shentsize) return error.InvalidElfFile;
619622

620-
_ = try preadFull(env_file, &sh_buf, str_section_off, shentsize);
623+
_ = try preadFull(file, &sh_buf, str_section_off, shentsize);
621624
const shstr32 = @ptrCast(*elf.Elf32_Shdr, @alignCast(@alignOf(elf.Elf32_Shdr), &sh_buf));
622625
const shstr64 = @ptrCast(*elf.Elf64_Shdr, @alignCast(@alignOf(elf.Elf64_Shdr), &sh_buf));
623626
const shstrtab_off = elfInt(is_64, need_bswap, shstr32.sh_offset, shstr64.sh_offset);
624627
const shstrtab_size = elfInt(is_64, need_bswap, shstr32.sh_size, shstr64.sh_size);
625628
var strtab_buf: [4096:0]u8 = undefined;
626629
const shstrtab_len = std.math.min(shstrtab_size, strtab_buf.len);
627-
const shstrtab_read_len = try preadFull(env_file, &strtab_buf, shstrtab_off, shstrtab_len);
630+
const shstrtab_read_len = try preadFull(file, &strtab_buf, shstrtab_off, shstrtab_len);
628631
const shstrtab = strtab_buf[0..shstrtab_read_len];
629632

630633
const shnum = elfInt(is_64, need_bswap, hdr32.e_shnum, hdr64.e_shnum);
@@ -634,7 +637,7 @@ pub const NativeTargetInfo = struct {
634637
// even when the ELF file is 32-bits.
635638
const sh_reserve: usize = @sizeOf(elf.Elf64_Shdr) - @sizeOf(elf.Elf32_Shdr);
636639
const sh_read_byte_len = try preadFull(
637-
env_file,
640+
file,
638641
sh_buf[0 .. sh_buf.len - sh_reserve],
639642
shoff,
640643
shentsize,
@@ -667,7 +670,7 @@ pub const NativeTargetInfo = struct {
667670

668671
if (dynstr) |ds| {
669672
const strtab_len = std.math.min(ds.size, strtab_buf.len);
670-
const strtab_read_len = try preadFull(env_file, &strtab_buf, ds.offset, shstrtab_len);
673+
const strtab_read_len = try preadFull(file, &strtab_buf, ds.offset, shstrtab_len);
671674
const strtab = strtab_buf[0..strtab_read_len];
672675
// TODO this pointer cast should not be necessary
673676
const rpath_list = mem.toSliceConst(u8, @ptrCast([*:0]u8, strtab[rpoff..].ptr));
@@ -763,7 +766,7 @@ pub const NativeTargetInfo = struct {
763766
};
764767
}
765768

766-
const LdInfo = struct {
769+
pub const LdInfo = struct {
767770
ld: DynamicLinker,
768771
abi: Target.Abi,
769772
};

0 commit comments

Comments
 (0)