Commit b12992cb01

Jakub Konka <kubkon@jakubkonka.com>
2022-08-18 15:32:15
macho: do not open file handle when building static archive
Firstly, opening a file handle is not really needed since we won't even use it, and secondly, this can cause AccessDenied errors on Windows when trying to move a directory from zig-cache/tmp/ to zig-cache/o/ since, without POSIX semantics, it is illegal to move directories with open handles to any of its resources.
1 parent f645972
Changed files (2)
src/link/MachO.zig
@@ -276,22 +276,14 @@ pub fn openPath(allocator: Allocator, options: link.Options) !*MachO {
     if (use_stage1 or options.emit == null) {
         return createEmpty(allocator, options);
     }
-    const emit = options.emit.?;
-    const file = try emit.directory.handle.createFile(emit.sub_path, .{
-        .truncate = false,
-        .read = true,
-        .mode = link.determineMode(options),
-    });
-    errdefer file.close();
 
+    const emit = options.emit.?;
     const self = try createEmpty(allocator, options);
     errdefer {
         self.base.file = null;
         self.base.destroy();
     }
 
-    self.base.file = file;
-
     if (build_options.have_llvm and options.use_llvm and options.module != null) {
         // TODO this intermediary_basename isn't enough; in the case of `zig build-exe`,
         // we also want to put the intermediary object file in the cache while the
@@ -307,6 +299,14 @@ pub fn openPath(allocator: Allocator, options: link.Options) !*MachO {
         return self;
     }
 
+    const file = try emit.directory.handle.createFile(emit.sub_path, .{
+        .truncate = false,
+        .read = true,
+        .mode = link.determineMode(options),
+    });
+    errdefer file.close();
+    self.base.file = file;
+
     if (!options.strip and options.module != null) blk: {
         // TODO once I add support for converting (and relocating) DWARF info from relocatable
         // object files, this check becomes unnecessary.
src/link.zig
@@ -772,12 +772,15 @@ pub const File = struct {
                     error.FileNotFound => {},
                     else => |e| return e,
                 }
-                try std.fs.rename(
+                std.fs.rename(
                     cache_directory.handle,
                     tmp_dir_sub_path,
                     cache_directory.handle,
                     o_sub_path,
-                );
+                ) catch |err| switch (err) {
+                    error.AccessDenied => unreachable, // We are most likely trying to move a dir with open handles to its resources
+                    else => |e| return e,
+                };
                 break;
             } else {
                 std.fs.rename(