9405
9406
9407
9408
9409
9410
9411
9412
9413
9414
9415
9416
9417
9418
9419
9420
9421
9422
9423
9424
9425
9426
9427
9428
9429
9430
9431
9432
9433
9434
9435
9436
9437
9438
9439
9440
9441
9442
9443
9444
9445
9446
9447
9448
9449
9450
9451
9452
9453
9454
9455
9456
9457
9458
9459
9460
9461
9462
9463
9464
9465
9466
9467
9468
9469
9470
9471
9472
9473
9474
9475
9476
9477
9478
9479
9480
9481
9482
9483
9484
fn fileLock(userdata: ?*anyopaque, file: File, lock: File.Lock) File.LockError!void {
if (native_os == .wasi) return error.FileLocksUnsupported;
const t: *Threaded = @ptrCast(@alignCast(userdata));
_ = t;
if (is_windows) {
const exclusive = switch (lock) {
.none => {
// To match the non-Windows behavior, unlock
var io_status_block: windows.IO_STATUS_BLOCK = undefined;
while (true) switch (windows.ntdll.NtUnlockFile(
file.handle,
&io_status_block,
&windows_lock_range_off,
&windows_lock_range_len,
0,
)) {
.SUCCESS => return,
.CANCELLED => continue,
.RANGE_NOT_LOCKED => return,
.ACCESS_VIOLATION => |err| return windows.statusBug(err), // bad io_status_block pointer
else => |status| return windows.unexpectedStatus(status),
};
},
.shared => false,
.exclusive => true,
};
var io_status_block: windows.IO_STATUS_BLOCK = undefined;
const syscall: Syscall = try .start();
while (true) switch (windows.ntdll.NtLockFile(
file.handle,
null,
null,
null,
&io_status_block,
&windows_lock_range_off,
&windows_lock_range_len,
null,
.FALSE,
.fromBool(exclusive),
)) {
.SUCCESS => return syscall.finish(),
.CANCELLED => {
try syscall.checkCancel();
continue;
},
.INSUFFICIENT_RESOURCES => return syscall.fail(error.SystemResources),
.LOCK_NOT_GRANTED => |err| return syscall.ntstatusBug(err), // passed FailImmediately=false
.ACCESS_VIOLATION => |err| return syscall.ntstatusBug(err), // bad io_status_block pointer
else => |status| return syscall.unexpectedNtstatus(status),
};
}
const operation: i32 = switch (lock) {
.none => posix.LOCK.UN,
.shared => posix.LOCK.SH,
.exclusive => posix.LOCK.EX,
};
const syscall: Syscall = try .start();
while (true) {
switch (posix.errno(posix.system.flock(file.handle, operation))) {
.SUCCESS => return syscall.finish(),
.INTR => {
try syscall.checkCancel();
continue;
},
else => |e| {
syscall.finish();
switch (e) {
.BADF => |err| return errnoBug(err),
.INVAL => |err| return errnoBug(err), // invalid parameters
.NOLCK => return error.SystemResources,
.AGAIN => |err| return errnoBug(err),
.OPNOTSUPP => return error.FileLocksUnsupported,
else => |err| return posix.unexpectedErrno(err),
}
},
}
}
}