authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-09-03 14:07:36-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-09-03 14:07:36-04:00
log39a80cf59e082b57606e5ddc074b5ae1337c0d79
tree2ef26ef912e20e10b032671af332bc0695b36d33
parent50e39069518a0c2643cd5e3189ad087b5fbed0c6
parent68818983aef0d44f43f9575d8207053d5b7250ba
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #6238 from Aransentin/master

Add the "sync" family of functions

5 files changed, 127 insertions(+), 0 deletions(-)

lib/std/c.zig+5
...@@ -330,3 +330,8 @@ pub const FILE = @Type(.Opaque);...@@ -330,3 +330,8 @@ pub const FILE = @Type(.Opaque);
330pub extern "c" fn dlopen(path: [*:0]const u8, mode: c_int) ?*c_void;330pub extern "c" fn dlopen(path: [*:0]const u8, mode: c_int) ?*c_void;
331pub extern "c" fn dlclose(handle: *c_void) c_int;331pub extern "c" fn dlclose(handle: *c_void) c_int;
332pub extern "c" fn dlsym(handle: ?*c_void, symbol: [*:0]const u8) ?*c_void;332pub extern "c" fn dlsym(handle: ?*c_void, symbol: [*:0]const u8) ?*c_void;
333
334pub extern "c" fn sync() void;
335pub extern "c" fn syncfs(fd: c_int) c_int;
336pub extern "c" fn fsync(fd: c_int) c_int;
337pub extern "c" fn fdatasync(fd: c_int) c_int;
lib/std/os.zig+68
...@@ -5331,3 +5331,71 @@ pub fn signalfd(fd: fd_t, mask: *const sigset_t, flags: u32) !fd_t {...@@ -5331,3 +5331,71 @@ pub fn signalfd(fd: fd_t, mask: *const sigset_t, flags: u32) !fd_t {
5331 else => |err| return std.os.unexpectedErrno(err),5331 else => |err| return std.os.unexpectedErrno(err),
5332 }5332 }
5333}5333}
5334
5335pub const SyncError = error{
5336 InputOutput,
5337 NoSpaceLeft,
5338 DiskQuota,
5339 AccessDenied,
5340} || UnexpectedError;
5341
5342/// Write all pending file contents and metadata modifications to all filesystems.
5343pub fn sync() void {
5344 system.sync();
5345}
5346
5347/// Write all pending file contents and metadata modifications to the filesystem which contains the specified file.
5348pub fn syncfs(fd: fd_t) SyncError!void {
5349 const rc = system.syncfs(fd);
5350 switch (errno(rc)) {
5351 0 => return,
5352 EBADF, EINVAL, EROFS => unreachable,
5353 EIO => return error.InputOutput,
5354 ENOSPC => return error.NoSpaceLeft,
5355 EDQUOT => return error.DiskQuota,
5356 else => |err| return std.os.unexpectedErrno(err),
5357 }
5358}
5359
5360/// Write all pending file contents and metadata modifications for the specified file descriptor to the underlying filesystem.
5361pub fn fsync(fd: fd_t) SyncError!void {
5362 if (std.Target.current.os.tag == .windows) {
5363 if (windows.kernel32.FlushFileBuffers(fd) != 0)
5364 return;
5365 switch (windows.kernel32.GetLastError()) {
5366 .SUCCESS => return,
5367 .INVALID_HANDLE => unreachable,
5368 .ACCESS_DENIED => return error.AccessDenied, // a sync was performed but the system couldn't update the access time
5369 .UNEXP_NET_ERR => return error.InputOutput,
5370 else => return error.InputOutput,
5371 }
5372 }
5373 const rc = system.fsync(fd);
5374 switch (errno(rc)) {
5375 0 => return,
5376 EBADF, EINVAL, EROFS => unreachable,
5377 EIO => return error.InputOutput,
5378 ENOSPC => return error.NoSpaceLeft,
5379 EDQUOT => return error.DiskQuota,
5380 else => |err| return std.os.unexpectedErrno(err),
5381 }
5382}
5383
5384/// Write all pending file contents for the specified file descriptor to the underlying filesystem, but not necessarily the metadata.
5385pub fn fdatasync(fd: fd_t) SyncError!void {
5386 if (std.Target.current.os.tag == .windows) {
5387 return fsync(fd) catch |err| switch (err) {
5388 SyncError.AccessDenied => return, // fdatasync doesn't promise that the access time was synced
5389 else => return err,
5390 };
5391 }
5392 const rc = system.fdatasync(fd);
5393 switch (errno(rc)) {
5394 0 => return,
5395 EBADF, EINVAL, EROFS => unreachable,
5396 EIO => return error.InputOutput,
5397 ENOSPC => return error.NoSpaceLeft,
5398 EDQUOT => return error.DiskQuota,
5399 else => |err| return std.os.unexpectedErrno(err),
5400 }
5401}
lib/std/os/linux.zig+16
...@@ -1226,6 +1226,22 @@ pub fn bpf(cmd: BPF.Cmd, attr: *BPF.Attr, size: u32) usize {...@@ -1226,6 +1226,22 @@ pub fn bpf(cmd: BPF.Cmd, attr: *BPF.Attr, size: u32) usize {
1226 return syscall3(.bpf, @enumToInt(cmd), @ptrToInt(attr), size);1226 return syscall3(.bpf, @enumToInt(cmd), @ptrToInt(attr), size);
1227}1227}
12281228
1229pub fn sync() void {
1230 _ = syscall0(.sync);
1231}
1232
1233pub fn syncfs(fd: fd_t) usize {
1234 return syscall1(.syncfs, @bitCast(usize, @as(isize, fd)));
1235}
1236
1237pub fn fsync(fd: fd_t) usize {
1238 return syscall1(.fsync, @bitCast(usize, @as(isize, fd)));
1239}
1240
1241pub fn fdatasync(fd: fd_t) usize {
1242 return syscall1(.fdatasync, @bitCast(usize, @as(isize, fd)));
1243}
1244
1229test "" {1245test "" {
1230 if (builtin.os.tag == .linux) {1246 if (builtin.os.tag == .linux) {
1231 _ = @import("linux/test.zig");1247 _ = @import("linux/test.zig");
lib/std/os/test.zig+36
...@@ -555,3 +555,39 @@ test "signalfd" {...@@ -555,3 +555,39 @@ test "signalfd" {
555 return error.SkipZigTest;555 return error.SkipZigTest;
556 _ = std.os.signalfd;556 _ = std.os.signalfd;
557}557}
558
559test "sync" {
560 if (builtin.os.tag != .linux)
561 return error.SkipZigTest;
562
563 var tmp = tmpDir(.{});
564 defer tmp.cleanup();
565
566 const test_out_file = "os_tmp_test";
567 const file = try tmp.dir.createFile(test_out_file, .{});
568 defer {
569 file.close();
570 tmp.dir.deleteFile(test_out_file) catch {};
571 }
572
573 os.sync();
574 try os.syncfs(file.handle);
575}
576
577test "fsync" {
578 if (builtin.os.tag != .linux and builtin.os.tag != .windows)
579 return error.SkipZigTest;
580
581 var tmp = tmpDir(.{});
582 defer tmp.cleanup();
583
584 const test_out_file = "os_tmp_test";
585 const file = try tmp.dir.createFile(test_out_file, .{});
586 defer {
587 file.close();
588 tmp.dir.deleteFile(test_out_file) catch {};
589 }
590
591 try os.fsync(file.handle);
592 try os.fdatasync(file.handle);
593}
lib/std/os/windows/kernel32.zig+2
...@@ -287,3 +287,5 @@ pub extern "kernel32" fn K32GetWsChangesEx(hProcess: HANDLE, lpWatchInfoEx: PPSA...@@ -287,3 +287,5 @@ pub extern "kernel32" fn K32GetWsChangesEx(hProcess: HANDLE, lpWatchInfoEx: PPSA
287pub extern "kernel32" fn K32InitializeProcessForWsWatch(hProcess: HANDLE) callconv(.Stdcall) BOOL;287pub extern "kernel32" fn K32InitializeProcessForWsWatch(hProcess: HANDLE) callconv(.Stdcall) BOOL;
288pub extern "kernel32" fn K32QueryWorkingSet(hProcess: HANDLE, pv: PVOID, cb: DWORD) callconv(.Stdcall) BOOL;288pub extern "kernel32" fn K32QueryWorkingSet(hProcess: HANDLE, pv: PVOID, cb: DWORD) callconv(.Stdcall) BOOL;
289pub extern "kernel32" fn K32QueryWorkingSetEx(hProcess: HANDLE, pv: PVOID, cb: DWORD) callconv(.Stdcall) BOOL;289pub extern "kernel32" fn K32QueryWorkingSetEx(hProcess: HANDLE, pv: PVOID, cb: DWORD) callconv(.Stdcall) BOOL;
290
291pub extern "kernel32" fn FlushFileBuffers(hFile: HANDLE) callconv(.Stdcall) BOOL;