| ... | @@ -666,8 +666,19 @@ pub const Dir = struct { | ... | @@ -666,8 +666,19 @@ pub const Dir = struct { |
| 666 | const path_w = try os.windows.cStrToPrefixedFileW(sub_path); | 666 | const path_w = try os.windows.cStrToPrefixedFileW(sub_path); |
| 667 | return self.openFileW(&path_w, flags); | 667 | return self.openFileW(&path_w, flags); |
| 668 | } | 668 | } |
| | 669 | |
| | 670 | // Use the O_ locking flags if the os supports them |
| | 671 | const lock_flag: u32 = lock_flag: { |
| | 672 | if (!flags.lock) break :lock_flag 0; |
| | 673 | if (flags.write) { |
| | 674 | break :lock_flag if (@hasDecl(os, "O_EXLOCK")) os.O_EXLOCK else 0; |
| | 675 | } else { |
| | 676 | break :lock_flag if (@hasDecl(os, "O_SHLOCK")) os.O_SHLOCK else 0; |
| | 677 | } |
| | 678 | }; |
| | 679 | |
| 669 | const O_LARGEFILE = if (@hasDecl(os, "O_LARGEFILE")) os.O_LARGEFILE else 0; | 680 | const O_LARGEFILE = if (@hasDecl(os, "O_LARGEFILE")) os.O_LARGEFILE else 0; |
| 670 | const os_flags = O_LARGEFILE | os.O_CLOEXEC | if (flags.write and flags.read) | 681 | const os_flags = lock_flag | O_LARGEFILE | os.O_CLOEXEC | if (flags.write and flags.read) |
| 671 | @as(u32, os.O_RDWR) | 682 | @as(u32, os.O_RDWR) |
| 672 | else if (flags.write) | 683 | else if (flags.write) |
| 673 | @as(u32, os.O_WRONLY) | 684 | @as(u32, os.O_WRONLY) |
| ... | @@ -678,18 +689,14 @@ pub const Dir = struct { | ... | @@ -678,18 +689,14 @@ pub const Dir = struct { |
| 678 | else | 689 | else |
| 679 | try os.openatC(self.fd, sub_path, os_flags, 0); | 690 | try os.openatC(self.fd, sub_path, os_flags, 0); |
| 680 | | 691 | |
| 681 | var locked = false; | 692 | // use fcntl file locking if no lock flag was given |
| 682 | if (flags.lock) { | 693 | if (flags.lock and lock_flag == 0) { |
| 683 | // TODO: integrate async I/O | 694 | // TODO: integrate async I/O |
| 684 | // mem.zeroes is used here because flock's structure can vary across architectures and systems | 695 | // mem.zeroes is used here because flock's structure can vary across architectures and systems |
| 685 | var flock = mem.zeroes(os.Flock); | 696 | var flock = mem.zeroes(os.Flock); |
| 686 | flock.l_type = if (flags.write) os.F_WRLCK else os.F_RDLCK; | 697 | flock.l_type = if (flags.write) os.F_WRLCK else os.F_RDLCK; |
| 687 | flock.l_whence = os.SEEK_SET; | 698 | flock.l_whence = os.SEEK_SET; |
| 688 | flock.l_start = 0; | | |
| 689 | flock.l_len = 0; | | |
| 690 | flock.l_pid = 0; | | |
| 691 | try os.fcntl(fd, os.F_SETLKW, &flock); | 699 | try os.fcntl(fd, os.F_SETLKW, &flock); |
| 692 | locked = true; | | |
| 693 | } | 700 | } |
| 694 | | 701 | |
| 695 | return File{ | 702 | return File{ |
| ... | @@ -735,8 +742,15 @@ pub const Dir = struct { | ... | @@ -735,8 +742,15 @@ pub const Dir = struct { |
| 735 | const path_w = try os.windows.cStrToPrefixedFileW(sub_path_c); | 742 | const path_w = try os.windows.cStrToPrefixedFileW(sub_path_c); |
| 736 | return self.createFileW(&path_w, flags); | 743 | return self.createFileW(&path_w, flags); |
| 737 | } | 744 | } |
| | 745 | |
| | 746 | // Use the O_ locking flags if the os supports them |
| | 747 | const lock_flag: u32 = lock_flag: { |
| | 748 | if (!flags.lock) break :lock_flag 0; |
| | 749 | break :lock_flag if (@hasDecl(os, "O_EXLOCK")) os.O_EXLOCK else 0; |
| | 750 | }; |
| | 751 | |
| 738 | const O_LARGEFILE = if (@hasDecl(os, "O_LARGEFILE")) os.O_LARGEFILE else 0; | 752 | const O_LARGEFILE = if (@hasDecl(os, "O_LARGEFILE")) os.O_LARGEFILE else 0; |
| 739 | const os_flags = O_LARGEFILE | os.O_CREAT | os.O_CLOEXEC | | 753 | const os_flags = lock_flag | O_LARGEFILE | os.O_CREAT | os.O_CLOEXEC | |
| 740 | (if (flags.truncate) @as(u32, os.O_TRUNC) else 0) | | 754 | (if (flags.truncate) @as(u32, os.O_TRUNC) else 0) | |
| 741 | (if (flags.read) @as(u32, os.O_RDWR) else os.O_WRONLY) | | 755 | (if (flags.read) @as(u32, os.O_RDWR) else os.O_WRONLY) | |
| 742 | (if (flags.exclusive) @as(u32, os.O_EXCL) else 0); | 756 | (if (flags.exclusive) @as(u32, os.O_EXCL) else 0); |
| ... | @@ -745,15 +759,12 @@ pub const Dir = struct { | ... | @@ -745,15 +759,12 @@ pub const Dir = struct { |
| 745 | else | 759 | else |
| 746 | try os.openatC(self.fd, sub_path_c, os_flags, flags.mode); | 760 | try os.openatC(self.fd, sub_path_c, os_flags, flags.mode); |
| 747 | | 761 | |
| 748 | if (flags.lock) { | 762 | if (flags.lock and lock_flag == 0) { |
| 749 | // TODO: integrate async I/O | 763 | // TODO: integrate async I/O |
| 750 | // mem.zeroes is used here because flock's structure can vary across architectures and systems | 764 | // mem.zeroes is used here because flock's structure can vary across architectures and systems |
| 751 | var flock = mem.zeroes(os.Flock); | 765 | var flock = mem.zeroes(os.Flock); |
| 752 | flock.l_type = os.F_WRLCK; | 766 | flock.l_type = os.F_WRLCK; |
| 753 | flock.l_whence = os.SEEK_SET; | 767 | flock.l_whence = os.SEEK_SET; |
| 754 | flock.l_start = 0; | | |
| 755 | flock.l_len = 0; | | |
| 756 | flock.l_pid = 0; | | |
| 757 | try os.fcntl(fd, os.F_SETLKW, &flock); | 768 | try os.fcntl(fd, os.F_SETLKW, &flock); |
| 758 | } | 769 | } |
| 759 | | 770 | |