llvm.org GIT mirror llvm / 03bcb21
[FileSystem] Split up the OpenFlags enumeration. This breaks the OpenFlags enumeration into two separate enumerations: OpenFlags and CreationDisposition. The first controls the behavior of the API depending on whether or not the target file already exists, and is not a flags-based enum. The second controls more flags-like values. This yields a more easy to understand API, while also allowing flags to be passed to the openForRead api, where most of the values didn't make sense before. This also makes the apis more testable as it becomes easy to enumerate all the configurations which make sense, so I've added many new tests to exercise all the different values. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@334221 91177308-0d34-0410-b5e6-96231b3b80d8 Zachary Turner 1 year, 2 months ago
20 changed file(s) with 609 addition(s) and 198 deletion(s). Raw diff Collapse all Expand all
675675 /// platform-specific error_code.
676676 std::error_code status_known(const Twine &path, bool &result);
677677
678 enum CreationDisposition : unsigned {
679 /// CD_CreateAlways - When opening a file:
680 /// * If it already exists, truncate it.
681 /// * If it does not already exist, create a new file.
682 CD_CreateAlways = 0,
683
684 /// CD_CreateNew - When opening a file:
685 /// * If it already exists, fail.
686 /// * If it does not already exist, create a new file.
687 CD_CreateNew = 1,
688
689 /// CD_OpenAlways - When opening a file:
690 /// * If it already exists, open the file with the offset set to 0.
691 /// * If it does not already exist, fail.
692 CD_OpenExisting = 2,
693
694 /// CD_OpenAlways - When opening a file:
695 /// * If it already exists, open the file with the offset set to 0.
696 /// * If it does not already exist, create a new file.
697 CD_OpenAlways = 3,
698 };
699
700 enum FileAccess : unsigned {
701 FA_Read = 1,
702 FA_Write = 2,
703 };
704
678705 enum OpenFlags : unsigned {
679 F_None = 0,
680
681 /// F_Excl - When opening a file, this flag makes raw_fd_ostream
682 /// report an error if the file already exists.
683 F_Excl = 1,
684
685 /// F_Append - When opening a file, if it already exists append to the
686 /// existing file instead of returning an error. This may not be specified
687 /// with F_Excl.
688 F_Append = 2,
689
690 /// F_NoTrunc - When opening a file, if it already exists don't truncate
691 /// the file contents. F_Append implies F_NoTrunc, but F_Append seeks to
692 /// the end of the file, which F_NoTrunc doesn't.
693 F_NoTrunc = 4,
706 OF_None = 0,
707 F_None = 0, // For compatibility
694708
695709 /// The file should be opened in text mode on platforms that make this
696710 /// distinction.
697 F_Text = 8,
698
699 /// Open the file for read and write.
700 F_RW = 16,
711 OF_Text = 1,
712 F_Text = 1, // For compatibility
713
714 /// The file should be opened in append mode.
715 OF_Append = 2,
716 F_Append = 2, // For compatibility
701717
702718 /// Delete the file on close. Only makes a difference on windows.
703 F_Delete = 32
719 OF_Delete = 4
704720 };
705721
706722 /// Create a uniquely named file.
823839 return A;
824840 }
825841
842 inline FileAccess operator|(FileAccess A, FileAccess B) {
843 return FileAccess(unsigned(A) | unsigned(B));
844 }
845
846 inline FileAccess &operator|=(FileAccess &A, FileAccess B) {
847 A = A | B;
848 return A;
849 }
850
826851 /// @brief Opens the file with the given name in a write-only or read-write
827852 /// mode, returning its open file descriptor. If the file does not exist, it
828853 /// is created.
839864 /// @returns errc::success if \a Name has been opened, otherwise a
840865 /// platform-specific error_code.
841866 std::error_code openFileForWrite(const Twine &Name, int &ResultFD,
842 OpenFlags Flags, unsigned Mode = 0666);
867 CreationDisposition Disp = CD_CreateAlways,
868 OpenFlags Flags = OF_None,
869 unsigned Mode = 0666);
843870
844871 /// @brief Opens the file with the given name in a write-only or read-write
845872 /// mode, returning its open file descriptor. If the file does not exist, it
854881 /// @param Mode The access permissions of the file, represented in octal.
855882 /// @returns a platform-specific file descriptor if \a Name has been opened,
856883 /// otherwise an error object.
857 Expected openNativeFileForWrite(const Twine &Name, OpenFlags Flags,
858 unsigned Mode = 0666);
884 Expected openNativeFileForWrite(const Twine &Name,
885 CreationDisposition Disp,
886 OpenFlags Flags, unsigned Mode = 0666);
887
888 /// @brief Opens the file with the given name in a write-only or read-write
889 /// mode, returning its open file descriptor. If the file does not exist, it
890 /// is created.
891 ///
892 /// The caller is responsible for closing the file descriptor once they are
893 /// finished with it.
894 ///
895 /// @param Name The path of the file to open, relative or absolute.
896 /// @param ResultFD If the file could be opened successfully, its descriptor
897 /// is stored in this location. Otherwise, this is set to -1.
898 /// @param Flags Additional flags used to determine whether the file should be
899 /// opened in, for example, read-write or in write-only mode.
900 /// @param Mode The access permissions of the file, represented in octal.
901 /// @returns errc::success if \a Name has been opened, otherwise a
902 /// platform-specific error_code.
903 std::error_code openFileForReadWrite(const Twine &Name, int &ResultFD,
904 CreationDisposition Disp, OpenFlags Flags,
905 unsigned Mode = 0666);
906
907 /// @brief Opens the file with the given name in a write-only or read-write
908 /// mode, returning its open file descriptor. If the file does not exist, it
909 /// is created.
910 ///
911 /// The caller is responsible for closing the freeing the file once they are
912 /// finished with it.
913 ///
914 /// @param Name The path of the file to open, relative or absolute.
915 /// @param Flags Additional flags used to determine whether the file should be
916 /// opened in, for example, read-write or in write-only mode.
917 /// @param Mode The access permissions of the file, represented in octal.
918 /// @returns a platform-specific file descriptor if \a Name has been opened,
919 /// otherwise an error object.
920 Expected openNativeFileForReadWrite(const Twine &Name,
921 CreationDisposition Disp,
922 OpenFlags Flags,
923 unsigned Mode = 0666);
859924
860925 /// @brief Opens the file with the given name in a read-only mode, returning
861926 /// its open file descriptor.
872937 /// @returns errc::success if \a Name has been opened, otherwise a
873938 /// platform-specific error_code.
874939 std::error_code openFileForRead(const Twine &Name, int &ResultFD,
940 OpenFlags Flags = OF_None,
875941 SmallVectorImpl *RealPath = nullptr);
876942
877943 /// @brief Opens the file with the given name in a read-only mode, returning
887953 /// @returns a platform-specific file descriptor if \a Name has been opened,
888954 /// otherwise an error object.
889955 Expected
890 openNativeFileForRead(const Twine &Name,
956 openNativeFileForRead(const Twine &Name, OpenFlags Flags = OF_None,
891957 SmallVectorImpl *RealPath = nullptr);
892958
893959 /// @brief Close the file object. This should be used instead of ::close for
3232
3333 namespace sys {
3434 namespace fs {
35 enum FileAccess : unsigned;
3536 enum OpenFlags : unsigned;
37 enum CreationDisposition : unsigned;
3638 } // end namespace fs
3739 } // end namespace sys
3840
396398 /// As a special case, if Filename is "-", then the stream will use
397399 /// STDOUT_FILENO instead of opening a file. This will not close the stdout
398400 /// descriptor.
401 raw_fd_ostream(StringRef Filename, std::error_code &EC);
399402 raw_fd_ostream(StringRef Filename, std::error_code &EC,
403 sys::fs::CreationDisposition Disp);
404 raw_fd_ostream(StringRef Filename, std::error_code &EC,
405 sys::fs::FileAccess Access);
406 raw_fd_ostream(StringRef Filename, std::error_code &EC,
407 sys::fs::OpenFlags Flags);
408 raw_fd_ostream(StringRef Filename, std::error_code &EC,
409 sys::fs::CreationDisposition Disp, sys::fs::FileAccess Access,
400410 sys::fs::OpenFlags Flags);
401411
402412 /// FD is the file descriptor that this writes to. If ShouldClose is true,
8181 size_t getBufferSize() const override { return Buffer.size(); }
8282
8383 Error commit() override {
84 using namespace sys::fs;
8485 int FD;
8586 std::error_code EC;
86 if (auto EC = openFileForWrite(FinalPath, FD, fs::F_None, Mode))
87 if (auto EC = openFileForWrite(FinalPath, FD, CD_CreateAlways, OF_None))
8788 return errorCodeToError(EC);
8889 raw_fd_ostream OS(FD, /*shouldClose=*/true, /*unbuffered=*/true);
8990 OS << StringRef((const char *)Buffer.base(), Buffer.size());
243243 getFileAux(const Twine &Filename, int64_t FileSize, uint64_t MapSize,
244244 uint64_t Offset, bool RequiresNullTerminator, bool IsVolatile) {
245245 int FD;
246 std::error_code EC = sys::fs::openFileForRead(Filename, FD);
246 std::error_code EC = sys::fs::openFileForRead(Filename, FD, sys::fs::OF_None);
247247
248248 if (EC)
249249 return EC;
363363 getReadWriteFile(const Twine &Filename, uint64_t FileSize, uint64_t MapSize,
364364 uint64_t Offset) {
365365 int FD;
366 std::error_code EC = sys::fs::openFileForWrite(
367 Filename, FD, sys::fs::F_RW | sys::fs::F_NoTrunc);
366 std::error_code EC = sys::fs::openFileForReadWrite(
367 Filename, FD, sys::fs::CD_OpenExisting, sys::fs::OF_None);
368368
369369 if (EC)
370370 return EC;
517517 ErrorOr>
518518 MemoryBuffer::getFileAsStream(const Twine &Filename) {
519519 int FD;
520 std::error_code EC = sys::fs::openFileForRead(Filename, FD);
520 std::error_code EC = sys::fs::openFileForRead(Filename, FD, sys::fs::OF_None);
521521 if (EC)
522522 return EC;
523523 ErrorOr> Ret =
168168 createUniqueEntity(const Twine &Model, int &ResultFD,
169169 SmallVectorImpl &ResultPath, bool MakeAbsolute,
170170 unsigned Mode, FSEntity Type,
171 sys::fs::OpenFlags Flags = sys::fs::F_RW) {
171 sys::fs::OpenFlags Flags = sys::fs::OF_None) {
172172 SmallString<128> ModelStorage;
173173 Model.toVector(ModelStorage);
174174
200200 switch (Type) {
201201 case FS_File: {
202202 if (std::error_code EC =
203 sys::fs::openFileForWrite(Twine(ResultPath.begin()), ResultFD,
204 Flags | sys::fs::F_Excl, Mode)) {
203 sys::fs::openFileForReadWrite(Twine(ResultPath.begin()), ResultFD,
204 sys::fs::CD_CreateNew, Flags, Mode)) {
205205 if (EC == errc::file_exists)
206206 goto retry_random_path;
207207 return EC;
928928
929929 std::error_code copy_file(const Twine &From, const Twine &To) {
930930 int ReadFD, WriteFD;
931 if (std::error_code EC = openFileForRead(From, ReadFD))
931 if (std::error_code EC = openFileForRead(From, ReadFD, OF_None))
932932 return EC;
933 if (std::error_code EC = openFileForWrite(To, WriteFD, F_None)) {
933 if (std::error_code EC =
934 openFileForWrite(To, WriteFD, CD_CreateAlways, OF_None)) {
934935 close(ReadFD);
935936 return EC;
936937 }
982983
983984 ErrorOr md5_contents(const Twine &Path) {
984985 int FD;
985 if (auto EC = openFileForRead(Path, FD))
986 if (auto EC = openFileForRead(Path, FD, OF_None))
986987 return EC;
987988
988989 auto Result = md5_contents(FD);
11791180 int FD;
11801181 SmallString<128> ResultPath;
11811182 if (std::error_code EC =
1182 createUniqueFile(Model, FD, ResultPath, Mode, F_Delete | F_RW))
1183 createUniqueFile(Model, FD, ResultPath, Mode, OF_Delete))
11831184 return errorCodeToError(EC);
11841185
11851186 TempFile Ret(ResultPath, FD);
158158 // Creates a TarWriter instance and returns it.
159159 Expected> TarWriter::create(StringRef OutputPath,
160160 StringRef BaseDir) {
161 using namespace sys::fs;
161162 int FD;
162 if (std::error_code EC = openFileForWrite(OutputPath, FD, sys::fs::F_None))
163 if (std::error_code EC =
164 openFileForWrite(OutputPath, FD, CD_CreateAlways, OF_None))
163165 return make_error("cannot open " + OutputPath, EC);
164166 return std::unique_ptr(new TarWriter(FD, BaseDir));
165167 }
721721 }
722722 #endif
723723
724 std::error_code openFileForRead(const Twine &Name, int &ResultFD,
725 SmallVectorImpl *RealPath) {
724 static int nativeOpenFlags(CreationDisposition Disp, OpenFlags Flags,
725 FileAccess Access) {
726 int Result = 0;
727 if (Access == FA_Read)
728 Result |= O_RDONLY;
729 else if (Access == FA_Write)
730 Result |= O_WRONLY;
731 else if (Access == (FA_Read | FA_Write))
732 Result |= O_RDWR;
733
734 // This is for compatibility with old code that assumed F_Append implied
735 // would open an existing file. See Windows/Path.inc for a longer comment.
736 if (Flags & F_Append)
737 Disp = CD_OpenAlways;
738
739 if (Disp == CD_CreateNew) {
740 Result |= O_CREAT; // Create if it doesn't exist.
741 Result |= O_EXCL; // Fail if it does.
742 } else if (Disp == CD_CreateAlways) {
743 Result |= O_CREAT; // Create if it doesn't exist.
744 Result |= O_TRUNC; // Truncate if it does.
745 } else if (Disp == CD_OpenAlways) {
746 Result |= O_CREAT; // Create if it doesn't exist.
747 } else if (Disp == CD_OpenExisting) {
748 // Nothing special, just don't add O_CREAT and we get these semantics.
749 }
750
751 if (Flags & F_Append)
752 Result |= O_APPEND;
753
754 #ifdef O_CLOEXEC
755 Result |= O_CLOEXEC;
756 #endif
757
758 return Result;
759 }
760
761 static std::error_code openFile(const Twine &Name, int &ResultFD,
762 CreationDisposition Disp, FileAccess Access,
763 OpenFlags Flags, unsigned Mode) {
764 int OpenFlags = nativeOpenFlags(Disp, Flags, Access);
765
726766 SmallString<128> Storage;
727767 StringRef P = Name.toNullTerminatedStringRef(Storage);
728 int OpenFlags = O_RDONLY;
729 #ifdef O_CLOEXEC
730 OpenFlags |= O_CLOEXEC;
731 #endif
732 if ((ResultFD = sys::RetryAfterSignal(-1, open, P.begin(), OpenFlags)) < 0)
768 if ((ResultFD = sys::RetryAfterSignal(-1, open, P.begin(), OpenFlags, Mode)) <
769 0)
733770 return std::error_code(errno, std::generic_category());
734771 #ifndef O_CLOEXEC
735772 int r = fcntl(ResultFD, F_SETFD, FD_CLOEXEC);
736773 (void)r;
737774 assert(r == 0 && "fcntl(F_SETFD, FD_CLOEXEC) failed");
738775 #endif
776 return std::error_code();
777 }
778
779 std::error_code openFileForRead(const Twine &Name, int &ResultFD,
780 OpenFlags Flags,
781 SmallVectorImpl *RealPath) {
782 std::error_code EC =
783 openFile(Name, ResultFD, CD_OpenExisting, FA_Read, Flags, 0666);
784 if (EC)
785 return EC;
786
739787 // Attempt to get the real name of the file, if the user asked
740788 if(!RealPath)
741789 return std::error_code();
755803 if (CharCount > 0)
756804 RealPath->append(Buffer, Buffer + CharCount);
757805 } else {
806 SmallString<128> Storage;
807 StringRef P = Name.toNullTerminatedStringRef(Storage);
808
758809 // Use ::realpath to get the real path name
759810 if (::realpath(P.begin(), Buffer) != nullptr)
760811 RealPath->append(Buffer, Buffer + strlen(Buffer));
763814 return std::error_code();
764815 }
765816
766 Expected openNativeFileForRead(const Twine &Name,
817 Expected openNativeFileForRead(const Twine &Name, OpenFlags Flags,
767818 SmallVectorImpl *RealPath) {
768819 file_t ResultFD;
769 std::error_code EC = openFileForRead(Name, ResultFD, RealPath);
820 std::error_code EC = openFileForRead(Name, ResultFD, Flags, RealPath);
770821 if (EC)
771822 return errorCodeToError(EC);
772823 return ResultFD;
773824 }
774825
775826 std::error_code openFileForWrite(const Twine &Name, int &ResultFD,
776 sys::fs::OpenFlags Flags, unsigned Mode) {
777 // Verify that we don't have both "append" and "excl".
778 assert((!(Flags & sys::fs::F_Excl) || !(Flags & sys::fs::F_Append)) &&
779 "Cannot specify both 'excl' and 'append' file creation flags!");
780
781 int OpenFlags = O_CREAT;
782
783 #ifdef O_CLOEXEC
784 OpenFlags |= O_CLOEXEC;
785 #endif
786
787 if (Flags & F_RW)
788 OpenFlags |= O_RDWR;
789 else
790 OpenFlags |= O_WRONLY;
791
792 if (Flags & F_Append)
793 OpenFlags |= O_APPEND;
794 else if (!(Flags & F_NoTrunc))
795 OpenFlags |= O_TRUNC;
796
797 if (Flags & F_Excl)
798 OpenFlags |= O_EXCL;
799
800 SmallString<128> Storage;
801 StringRef P = Name.toNullTerminatedStringRef(Storage);
802 if ((ResultFD = sys::RetryAfterSignal(-1, open, P.begin(), OpenFlags, Mode)) < 0)
803 return std::error_code(errno, std::generic_category());
804 #ifndef O_CLOEXEC
805 int r = fcntl(ResultFD, F_SETFD, FD_CLOEXEC);
806 (void)r;
807 assert(r == 0 && "fcntl(F_SETFD, FD_CLOEXEC) failed");
808 #endif
809 return std::error_code();
810 }
811
812 Expected openNativeFileForWrite(const Twine &Name, OpenFlags Flags,
813 unsigned Mode) {
827 CreationDisposition Disp, OpenFlags Flags,
828 unsigned Mode) {
829 return openFile(Name, ResultFD, Disp, FA_Write, Flags, Mode);
830 }
831
832 Expected openNativeFileForWrite(const Twine &Name,
833 CreationDisposition Disp,
834 OpenFlags Flags, unsigned Mode) {
814835 file_t ResultFD;
815 std::error_code EC = openFileForWrite(Name, ResultFD, Flags, Mode);
836 std::error_code EC = openFileForWrite(Name, ResultFD, Disp, Flags, Mode);
837 if (EC)
838 return errorCodeToError(EC);
839 return ResultFD;
840 }
841
842 std::error_code openFileForReadWrite(const Twine &Name, int &ResultFD,
843 CreationDisposition Disp, OpenFlags Flags,
844 unsigned Mode) {
845 return openFile(Name, ResultFD, Disp, FA_Read | FA_Write, Flags, Mode);
846 }
847
848 Expected openNativeFileForReadWrite(const Twine &Name,
849 CreationDisposition Disp,
850 OpenFlags Flags, unsigned Mode) {
851 file_t ResultFD;
852 std::error_code EC = openFileForReadWrite(Name, ResultFD, Disp, Flags, Mode);
816853 if (EC)
817854 return errorCodeToError(EC);
818855 return ResultFD;
10341034 return Status;
10351035 }
10361036
1037 static std::error_code directoryRealPath(const Twine &Name,
1038 SmallVectorImpl &RealPath) {
1039 SmallVector PathUTF16;
1040
1041 if (std::error_code EC = widenPath(Name, PathUTF16))
1042 return EC;
1043
1044 HANDLE H =
1045 ::CreateFileW(PathUTF16.begin(), GENERIC_READ,
1046 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1047 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
1048 if (H == INVALID_HANDLE_VALUE)
1049 return mapWindowsError(GetLastError());
1050 std::error_code EC = realPathFromHandle(H, RealPath);
1051 ::CloseHandle(H);
1052 return EC;
1053 }
1054
10551037 static std::error_code nativeFileToFd(Expected H, int &ResultFD,
1056 int OpenFlags) {
1038 OpenFlags Flags) {
1039 int CrtOpenFlags = 0;
1040 if (Flags & OF_Append)
1041 CrtOpenFlags |= _O_APPEND;
1042
1043 if (Flags & OF_Text)
1044 CrtOpenFlags |= _O_TEXT;
1045
10571046 ResultFD = -1;
10581047 if (!H)
10591048 return errorToErrorCode(H.takeError());
10601049
1061 ResultFD = ::_open_osfhandle(intptr_t(*H), OpenFlags);
1050 ResultFD = ::_open_osfhandle(intptr_t(*H), CrtOpenFlags);
10621051 if (ResultFD == -1) {
10631052 ::CloseHandle(*H);
10641053 return mapWindowsError(ERROR_INVALID_HANDLE);
10661055 return std::error_code();
10671056 }
10681057
1069 std::error_code openFileForRead(const Twine &Name, int &ResultFD,
1070 SmallVectorImpl *RealPath) {
1071 Expected NativeFile = openNativeFileForRead(Name, RealPath);
1072 return nativeFileToFd(std::move(NativeFile), ResultFD, 0);
1073 }
1074
1075 Expected openNativeFileForRead(const Twine &Name,
1076 SmallVectorImpl *RealPath) {
1058 static DWORD nativeOpenFlags(OpenFlags Flags) {
1059 DWORD Result = 0;
1060 if (Flags & OF_Delete)
1061 Result |= FILE_FLAG_DELETE_ON_CLOSE;
1062
1063 if (Result == 0)
1064 Result = FILE_ATTRIBUTE_NORMAL;
1065 return Result;
1066 }
1067
1068 static DWORD nativeDisposition(CreationDisposition Disp, OpenFlags Flags) {
1069 // This is a compatibility hack. Really we should respect the creation
1070 // disposition, but a lot of old code relied on the implicit assumption that
1071 // OF_Append implied it would open an existing file. Since the disposition is
1072 // now explicit and defaults to CD_CreateAlways, this assumption would cause
1073 // any usage of OF_Append to append to a new file, even if the file already
1074 // existed. A better solution might have two new creation dispositions:
1075 // CD_AppendAlways and CD_AppendNew. This would also address the problem of
1076 // OF_Append being used on a read-only descriptor, which doesn't make sense.
1077 if (Flags & OF_Append)
1078 return OPEN_ALWAYS;
1079
1080 switch (Disp) {
1081 case CD_CreateAlways:
1082 return CREATE_ALWAYS;
1083 case CD_CreateNew:
1084 return CREATE_NEW;
1085 case CD_OpenAlways:
1086 return OPEN_ALWAYS;
1087 case CD_OpenExisting:
1088 return OPEN_EXISTING;
1089 }
1090 llvm_unreachable("unreachable!");
1091 }
1092
1093 static DWORD nativeAccess(FileAccess Access, OpenFlags Flags) {
1094 DWORD Result = 0;
1095 if (Access & FA_Read)
1096 Result |= GENERIC_READ;
1097 if (Access & FA_Write)
1098 Result |= GENERIC_WRITE;
1099 if (Flags & OF_Delete)
1100 Result |= DELETE;
1101 return Result;
1102 }
1103
1104 static Expected nativeOpenFile(const Twine &Name, DWORD Disp,
1105 DWORD Access, DWORD Flags) {
10771106 SmallVector PathUTF16;
1078
10791107 if (std::error_code EC = widenPath(Name, PathUTF16))
10801108 return errorCodeToError(EC);
10811109
10821110 HANDLE H =
1083 ::CreateFileW(PathUTF16.begin(), GENERIC_READ,
1111 ::CreateFileW(PathUTF16.begin(), Access,
10841112 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1085 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1113 NULL, Disp, Flags, NULL);
10861114 if (H == INVALID_HANDLE_VALUE) {
10871115 DWORD LastError = ::GetLastError();
10881116 std::error_code EC = mapWindowsError(LastError);
10951123 return errorCodeToError(make_error_code(errc::is_a_directory));
10961124 return errorCodeToError(EC);
10971125 }
1126 return H;
1127 }
1128
1129 static Expected openFile(const Twine &Name, CreationDisposition Disp,
1130 FileAccess Access, OpenFlags Flags) {
1131 // Verify that we don't have both "append" and "excl".
1132 assert((!(Disp == CD_CreateNew) || !(Flags & OF_Append)) &&
1133 "Cannot specify both 'CreateNew' and 'Append' file creation flags!");
1134
1135 DWORD NativeFlags = nativeOpenFlags(Flags);
1136 DWORD NativeDisp = nativeDisposition(Disp, Flags);
1137 DWORD NativeAccess = nativeAccess(Access, Flags);
1138
1139 return nativeOpenFile(Name, NativeDisp, NativeAccess, NativeFlags);
1140 }
1141
1142 static std::error_code directoryRealPath(const Twine &Name,
1143 SmallVectorImpl &RealPath) {
1144 Expected EF = nativeOpenFile(Name, OPEN_EXISTING, GENERIC_READ,
1145 FILE_FLAG_BACKUP_SEMANTICS);
1146 if (!EF)
1147 return errorToErrorCode(EF.takeError());
1148
1149 std::error_code EC = realPathFromHandle(*EF, RealPath);
1150 ::CloseHandle(*EF);
1151 return EC;
1152 }
1153
1154 std::error_code openFileForRead(const Twine &Name, int &ResultFD,
1155 OpenFlags Flags,
1156 SmallVectorImpl *RealPath) {
1157 Expected NativeFile = openNativeFileForRead(Name, Flags, RealPath);
1158 return nativeFileToFd(std::move(NativeFile), ResultFD, OF_None);
1159 }
1160
1161 Expected openNativeFileForRead(const Twine &Name, OpenFlags Flags,
1162 SmallVectorImpl *RealPath) {
1163
1164 Expected Result = openFile(Name, CD_OpenExisting, FA_Read, Flags);
10981165
10991166 // Fetch the real name of the file, if the user asked
1100 if (RealPath)
1101 realPathFromHandle(H, *RealPath);
1102
1103 return H;
1167 if (Result && RealPath)
1168 realPathFromHandle(*Result, *RealPath);
1169
1170 return std::move(Result);
11041171 }
11051172
11061173 std::error_code openFileForWrite(const Twine &Name, int &ResultFD,
1107 sys::fs::OpenFlags Flags, unsigned Mode) {
1108 int OpenFlags = 0;
1109 if (Flags & F_Append)
1110 OpenFlags |= _O_APPEND;
1111
1112 if (Flags & F_Text)
1113 OpenFlags |= _O_TEXT;
1114
1115 Expected NativeFile = openNativeFileForWrite(Name, Flags, Mode);
1116 return nativeFileToFd(std::move(NativeFile), ResultFD, OpenFlags);
1117 }
1118
1119 Expected openNativeFileForWrite(const Twine &Name, OpenFlags Flags,
1120 unsigned Mode) {
1121 // Verify that we don't have both "append" and "excl".
1122 assert((!(Flags & sys::fs::F_Excl) || !(Flags & sys::fs::F_Append)) &&
1123 "Cannot specify both 'excl' and 'append' file creation flags!");
1124
1125 SmallVector PathUTF16;
1126
1127 if (std::error_code EC = widenPath(Name, PathUTF16))
1128 return errorCodeToError(EC);
1129
1130 DWORD CreationDisposition;
1131 if (Flags & F_Excl)
1132 CreationDisposition = CREATE_NEW;
1133 else if ((Flags & F_Append) || (Flags & F_NoTrunc))
1134 CreationDisposition = OPEN_ALWAYS;
1135 else
1136 CreationDisposition = CREATE_ALWAYS;
1137
1138 DWORD Access = GENERIC_WRITE;
1139 DWORD Attributes = FILE_ATTRIBUTE_NORMAL;
1140 if (Flags & F_RW)
1141 Access |= GENERIC_READ;
1142 if (Flags & F_Delete) {
1143 Access |= DELETE;
1144 Attributes |= FILE_FLAG_DELETE_ON_CLOSE;
1145 }
1146
1147 HANDLE H =
1148 ::CreateFileW(PathUTF16.data(), Access,
1149 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
1150 NULL, CreationDisposition, Attributes, NULL);
1151
1152 if (H == INVALID_HANDLE_VALUE) {
1153 DWORD LastError = ::GetLastError();
1154 std::error_code EC = mapWindowsError(LastError);
1155 // Provide a better error message when trying to open directories.
1156 // This only runs if we failed to open the file, so there is probably
1157 // no performances issues.
1158 if (LastError != ERROR_ACCESS_DENIED)
1159 return errorCodeToError(EC);
1160 if (is_directory(Name))
1161 return errorCodeToError(make_error_code(errc::is_a_directory));
1162 return errorCodeToError(EC);
1163 }
1164
1165 return H;
1174 CreationDisposition Disp, OpenFlags Flags,
1175 unsigned Mode) {
1176 Expected NativeFile = openNativeFileForWrite(Name, Disp, Flags, Mode);
1177 if (!NativeFile)
1178 return errorToErrorCode(NativeFile.takeError());
1179
1180 return nativeFileToFd(std::move(NativeFile), ResultFD, Flags);
1181 }
1182
1183 Expected openNativeFileForWrite(const Twine &Name,
1184 CreationDisposition Disp,
1185 OpenFlags Flags, unsigned Mode) {
1186 return openFile(Name, Disp, FA_Write, Flags);
1187 }
1188
1189 std::error_code openFileForReadWrite(const Twine &Name, int &ResultFD,
1190 CreationDisposition Disp, OpenFlags Flags,
1191 unsigned Mode) {
1192 Expected NativeFile =
1193 openNativeFileForReadWrite(Name, Disp, Flags, Mode);
1194 if (!NativeFile)
1195 return errorToErrorCode(NativeFile.takeError());
1196
1197 return nativeFileToFd(std::move(NativeFile), ResultFD, Flags);
1198 }
1199
1200 Expected openNativeFileForReadWrite(const Twine &Name,
1201 CreationDisposition Disp,
1202 OpenFlags Flags, unsigned Mode) {
1203 return openFile(Name, Disp, FA_Write | FA_Read, Flags);
11661204 }
11671205
11681206 void closeFile(file_t &F) {
12381276 return directoryRealPath(path, dest);
12391277
12401278 int fd;
1241 if (std::error_code EC = llvm::sys::fs::openFileForRead(path, fd, &dest))
1279 if (std::error_code EC =
1280 llvm::sys::fs::openFileForRead(path, fd, OF_None, &dest))
12421281 return EC;
12431282 ::close(fd);
12441283 return std::error_code();
495495 llvm::sys::writeFileWithEncoding(StringRef FileName, StringRef Contents,
496496 WindowsEncodingMethod Encoding) {
497497 std::error_code EC;
498 llvm::raw_fd_ostream OS(FileName, EC, llvm::sys::fs::OpenFlags::F_Text);
498 llvm::raw_fd_ostream OS(FileName, EC, llvm::sys::fs::F_Text);
499499 if (EC)
500500 return EC;
501501
497497 //===----------------------------------------------------------------------===//
498498
499499 static int getFD(StringRef Filename, std::error_code &EC,
500 sys::fs::CreationDisposition Disp, sys::fs::FileAccess Access,
500501 sys::fs::OpenFlags Flags) {
502 assert((Access & sys::fs::FA_Write) &&
503 "Cannot make a raw_ostream from a read-only descriptor!");
504
501505 // Handle "-" as stdout. Note that when we do this, we consider ourself
502506 // the owner of stdout and may set the "binary" flag globally based on Flags.
503507 if (Filename == "-") {
504508 EC = std::error_code();
505509 // If user requested binary then put stdout into binary mode if
506510 // possible.
507 if (!(Flags & sys::fs::F_Text))
511 if (!(Flags & sys::fs::OF_Text))
508512 sys::ChangeStdoutToBinary();
509513 return STDOUT_FILENO;
510514 }
511515
512516 int FD;
513 EC = sys::fs::openFileForWrite(Filename, FD, Flags);
517 if (Access & sys::fs::FA_Read)
518 EC = sys::fs::openFileForReadWrite(Filename, FD, Disp, Flags);
519 else
520 EC = sys::fs::openFileForWrite(Filename, FD, Disp, Flags);
514521 if (EC)
515522 return -1;
516523
517524 return FD;
518525 }
519526
527 raw_fd_ostream::raw_fd_ostream(StringRef Filename, std::error_code &EC)
528 : raw_fd_ostream(Filename, EC, sys::fs::CD_CreateAlways, sys::fs::FA_Write,
529 sys::fs::OF_None) {}
530
531 raw_fd_ostream::raw_fd_ostream(StringRef Filename, std::error_code &EC,
532 sys::fs::CreationDisposition Disp)
533 : raw_fd_ostream(Filename, EC, Disp, sys::fs::FA_Write, sys::fs::OF_None) {}
534
535 raw_fd_ostream::raw_fd_ostream(StringRef Filename, std::error_code &EC,
536 sys::fs::FileAccess Access)
537 : raw_fd_ostream(Filename, EC, sys::fs::CD_CreateAlways, Access,
538 sys::fs::OF_None) {}
539
520540 raw_fd_ostream::raw_fd_ostream(StringRef Filename, std::error_code &EC,
521541 sys::fs::OpenFlags Flags)
522 : raw_fd_ostream(getFD(Filename, EC, Flags), true) {}
542 : raw_fd_ostream(Filename, EC, sys::fs::CD_CreateAlways, sys::fs::FA_Write,
543 Flags) {}
544
545 raw_fd_ostream::raw_fd_ostream(StringRef Filename, std::error_code &EC,
546 sys::fs::CreationDisposition Disp,
547 sys::fs::FileAccess Access,
548 sys::fs::OpenFlags Flags)
549 : raw_fd_ostream(getFD(Filename, EC, Disp, Access, Flags), true) {}
523550
524551 /// FD is the file descriptor that this writes to. If ShouldClose is true, this
525552 /// closes the file when the stream is destroyed.
389389
390390 int FD;
391391 failIfError(sys::fs::openFileForWrite(sys::path::filename(Name), FD,
392 sys::fs::CD_CreateAlways,
392393 sys::fs::F_None, Mode),
393394 Name);
394395
6464 return errorCodeToError(E);
6565
6666 std::error_code E;
67 raw_ostream *RawStream = new raw_fd_ostream(FullPath, E, sys::fs::F_RW);
67 raw_ostream *RawStream =
68 new raw_fd_ostream(FullPath, E, sys::fs::FA_Read | sys::fs::FA_Write);
6869 auto OS = CoveragePrinter::OwnedStream(RawStream);
6970 if (E)
7071 return errorCodeToError(E);
7474 return 1;
7575
7676 int FD;
77 if (auto Err =
78 sys::fs::openFileForWrite(OutputFilename, FD, sys::fs::F_None)) {
77 if (auto Err = sys::fs::openFileForWrite(OutputFilename, FD)) {
7978 errs() << "error: " << Err.message() << "\n";
8079 return 1;
8180 }
257257 } else {
258258 int ResultFD = 0;
259259 if (auto E = llvm::errorCodeToError(
260 openFileForWrite(Filename, ResultFD, llvm::sys::fs::F_Text))) {
260 openFileForWrite(Filename, ResultFD, llvm::sys::fs::CD_CreateAlways,
261 llvm::sys::fs::F_Text))) {
261262 return E;
262263 }
263264 llvm::raw_fd_ostream Ostr(ResultFD, true /*shouldClose*/);
165165 }
166166 std::error_code ErrorCode;
167167 llvm::raw_fd_ostream ClustersOS(OutputFilename, ErrorCode,
168 llvm::sys::fs::F_RW);
169 ExitOnErr(llvm::errorCodeToError(ErrorCode));
170 ExitOnErr(Analyzer.run(ClustersOS));
168 llvm::sys::fs::FA_Read |
169 llvm::sys::fs::FA_Write);
170 if (ErrorCode)
171 llvm::report_fatal_error("cannot open out file: " + OutputFilename);
172 if (auto Err = Analyzer.run(ClustersOS))
173 llvm::report_fatal_error(std::move(Err));
171174 }
172175
173176 static void analysisMain() {
170170 "No more than one output file should be provided (using /FO flag).");
171171
172172 std::error_code EC;
173 auto FOut =
174 llvm::make_unique(OutArgsInfo[0], EC, sys::fs::F_RW);
173 auto FOut = llvm::make_unique(
174 OutArgsInfo[0], EC, sys::fs::FA_Read | sys::fs::FA_Write);
175175 if (EC)
176176 fatalError("Error opening output file '" + OutArgsInfo[0] +
177177 "': " + EC.message());
5959 sys::path::append(TmpFileLock, "file.lock-000");
6060
6161 int FD;
62 EC = sys::fs::openFileForWrite(StringRef(TmpFileLock), FD, sys::fs::F_None);
62 EC = sys::fs::openFileForWrite(StringRef(TmpFileLock), FD);
6363 ASSERT_FALSE(EC);
6464
6565 int Ret = close(FD);
4848 } else { \
4949 }
5050
51 #define ASSERT_ERROR(x) \
52 if (!x) { \
53 SmallString<128> MessageStorage; \
54 raw_svector_ostream Message(MessageStorage); \
55 Message << #x ": did not return a failure error code.\n"; \
56 GTEST_FATAL_FAILURE_(MessageStorage.c_str()); \
57 }
58
5159 namespace {
60
61 struct FileDescriptorCloser {
62 explicit FileDescriptorCloser(int FD) : FD(FD) {}
63 ~FileDescriptorCloser() { ::close(FD); }
64 int FD;
65 };
5266
5367 TEST(is_separator, Works) {
5468 EXPECT_TRUE(path::is_separator('/'));
435449 /// Unique temporary directory in which all created filesystem entities must
436450 /// be placed. It is removed at the end of each test (must be empty).
437451 SmallString<128> TestDirectory;
452 SmallString<128> NonExistantFile;
438453
439454 void SetUp() override {
440455 ASSERT_NO_ERROR(
442457 // We don't care about this specific file.
443458 errs() << "Test Directory: " << TestDirectory << '\n';
444459 errs().flush();
460 NonExistantFile = TestDirectory;
461
462 // Even though this value is hardcoded, is a 128-bit GUID, so we should be
463 // guaranteed that this file will never exist.
464 sys::path::append(NonExistantFile, "1B28B495C16344CB9822E588CD4C3EF0");
445465 }
446466
447467 void TearDown() override { ASSERT_NO_ERROR(fs::remove(TestDirectory.str())); }
12181238 // Open the file for read
12191239 int FileDescriptor2;
12201240 SmallString<64> ResultPath;
1221 ASSERT_NO_ERROR(
1222 fs::openFileForRead(Twine(TempPath), FileDescriptor2, &ResultPath))
1241 ASSERT_NO_ERROR(fs::openFileForRead(Twine(TempPath), FileDescriptor2,
1242 fs::OF_None, &ResultPath))
12231243
12241244 // If we succeeded, check that the paths are the same (modulo case):
12251245 if (!ResultPath.empty()) {
12341254 ::close(FileDescriptor);
12351255 }
12361256
1257 static void createFileWithData(const Twine &Path, bool ShouldExistBefore,
1258 fs::CreationDisposition Disp, StringRef Data) {
1259 int FD;
1260 ASSERT_EQ(ShouldExistBefore, fs::exists(Path));
1261 ASSERT_NO_ERROR(fs::openFileForWrite(Path, FD, Disp));
1262 FileDescriptorCloser Closer(FD);
1263 ASSERT_TRUE(fs::exists(Path));
1264
1265 ASSERT_EQ(Data.size(), (size_t)write(FD, Data.data(), Data.size()));
1266 }
1267
1268 static void verifyFileContents(const Twine &Path, StringRef Contents) {
1269 auto Buffer = MemoryBuffer::getFile(Path);
1270 ASSERT_TRUE((bool)Buffer);
1271 StringRef Data = Buffer.get()->getBuffer();
1272 ASSERT_EQ(Data, Contents);
1273 }
1274
1275 TEST_F(FileSystemTest, CreateNew) {
1276 int FD;
1277 Optional Closer;
1278
1279 // Succeeds if the file does not exist.
1280 ASSERT_FALSE(fs::exists(NonExistantFile));
1281 ASSERT_NO_ERROR(fs::openFileForWrite(NonExistantFile, FD, fs::CD_CreateNew));
1282 ASSERT_TRUE(fs::exists(NonExistantFile));
1283
1284 FileRemover Cleanup(NonExistantFile);
1285 Closer.emplace(FD);
1286
1287 // And creates a file of size 0.
1288 sys::fs::file_status Status;
1289 ASSERT_NO_ERROR(sys::fs::status(FD, Status));
1290 EXPECT_EQ(0ULL, Status.getSize());
1291
1292 // Close this first, before trying to re-open the file.
1293 Closer.reset();
1294
1295 // But fails if the file does exist.
1296 ASSERT_ERROR(fs::openFileForWrite(NonExistantFile, FD, fs::CD_CreateNew));
1297 }
1298
1299 TEST_F(FileSystemTest, CreateAlways) {
1300 int FD;
1301 Optional Closer;
1302
1303 // Succeeds if the file does not exist.
1304 ASSERT_FALSE(fs::exists(NonExistantFile));
1305 ASSERT_NO_ERROR(
1306 fs::openFileForWrite(NonExistantFile, FD, fs::CD_CreateAlways));
1307
1308 Closer.emplace(FD);
1309
1310 ASSERT_TRUE(fs::exists(NonExistantFile));
1311
1312 FileRemover Cleanup(NonExistantFile);
1313
1314 // And creates a file of size 0.
1315 uint64_t FileSize;
1316 ASSERT_NO_ERROR(sys::fs::file_size(NonExistantFile, FileSize));
1317 ASSERT_EQ(0ULL, FileSize);
1318
1319 // If we write some data to it re-create it with CreateAlways, it succeeds and
1320 // truncates to 0 bytes.
1321 ASSERT_EQ(4, write(FD, "Test", 4));
1322
1323 Closer.reset();
1324
1325 ASSERT_NO_ERROR(sys::fs::file_size(NonExistantFile, FileSize));
1326 ASSERT_EQ(4ULL, FileSize);
1327
1328 ASSERT_NO_ERROR(
1329 fs::openFileForWrite(NonExistantFile, FD, fs::CD_CreateAlways));
1330 Closer.emplace(FD);
1331 ASSERT_NO_ERROR(sys::fs::file_size(NonExistantFile, FileSize));
1332 ASSERT_EQ(0ULL, FileSize);
1333 }
1334
1335 TEST_F(FileSystemTest, OpenExisting) {
1336 int FD;
1337
1338 // Fails if the file does not exist.
1339 ASSERT_FALSE(fs::exists(NonExistantFile));
1340 ASSERT_ERROR(fs::openFileForWrite(NonExistantFile, FD, fs::CD_OpenExisting));
1341 ASSERT_FALSE(fs::exists(NonExistantFile));
1342
1343 // Make a dummy file now so that we can try again when the file does exist.
1344 createFileWithData(NonExistantFile, false, fs::CD_CreateNew, "Fizz");
1345 FileRemover Cleanup(NonExistantFile);
1346 uint64_t FileSize;
1347 ASSERT_NO_ERROR(sys::fs::file_size(NonExistantFile, FileSize));
1348 ASSERT_EQ(4ULL, FileSize);
1349
1350 // If we re-create it with different data, it overwrites rather than
1351 // appending.
1352 createFileWithData(NonExistantFile, true, fs::CD_OpenExisting, "Buzz");
1353 verifyFileContents(NonExistantFile, "Buzz");
1354 }
1355
1356 TEST_F(FileSystemTest, OpenAlways) {
1357 // Succeeds if the file does not exist.
1358 createFileWithData(NonExistantFile, false, fs::CD_OpenAlways, "Fizz");
1359 FileRemover Cleanup(NonExistantFile);
1360 uint64_t FileSize;
1361 ASSERT_NO_ERROR(sys::fs::file_size(NonExistantFile, FileSize));
1362 ASSERT_EQ(4ULL, FileSize);
1363
1364 // Now re-open it and write again, verifying the contents get over-written.
1365 createFileWithData(NonExistantFile, true, fs::CD_OpenAlways, "Bu");
1366 verifyFileContents(NonExistantFile, "Buzz");
1367 }
1368
1369 TEST_F(FileSystemTest, AppendSetsCorrectFileOffset) {
1370 fs::CreationDisposition Disps[] = {fs::CD_CreateAlways, fs::CD_OpenAlways,
1371 fs::CD_OpenExisting};
1372
1373 // Write some data and re-open it with every possible disposition (this is a
1374 // hack that shouldn't work, but is left for compatibility. F_Append
1375 // overrides
1376 // the specified disposition.
1377 for (fs::CreationDisposition Disp : Disps) {
1378 int FD;
1379 Optional Closer;
1380
1381 createFileWithData(NonExistantFile, false, fs::CD_CreateNew, "Fizz");
1382
1383 FileRemover Cleanup(NonExistantFile);
1384
1385 uint64_t FileSize;
1386 ASSERT_NO_ERROR(sys::fs::file_size(NonExistantFile, FileSize));
1387 ASSERT_EQ(4ULL, FileSize);
1388 ASSERT_NO_ERROR(
1389 fs::openFileForWrite(NonExistantFile, FD, Disp, fs::OF_Append));
1390 Closer.emplace(FD);
1391 ASSERT_NO_ERROR(sys::fs::file_size(NonExistantFile, FileSize));
1392 ASSERT_EQ(4ULL, FileSize);
1393
1394 ASSERT_EQ(4, write(FD, "Buzz", 4));
1395 Closer.reset();
1396
1397 verifyFileContents(NonExistantFile, "FizzBuzz");
1398 }
1399 }
1400
1401 static void verifyRead(int FD, StringRef Data, bool ShouldSucceed) {
1402 std::vector Buffer;
1403 Buffer.resize(Data.size());
1404 int Result = ::read(FD, Buffer.data(), Buffer.size());
1405 if (ShouldSucceed) {
1406 ASSERT_EQ((size_t)Result, Data.size());
1407 ASSERT_EQ(Data, StringRef(Buffer.data(), Buffer.size()));
1408 } else {
1409 ASSERT_EQ(-1, Result);
1410 ASSERT_EQ(EBADF, errno);
1411 }
1412 }
1413
1414 static void verifyWrite(int FD, StringRef Data, bool ShouldSucceed) {
1415 int Result = ::write(FD, Data.data(), Data.size());
1416 if (ShouldSucceed)
1417 ASSERT_EQ((size_t)Result, Data.size());
1418 else {
1419 ASSERT_EQ(-1, Result);
1420 ASSERT_EQ(EBADF, errno);
1421 }
1422 }
1423
1424 TEST_F(FileSystemTest, ReadOnlyFileCantWrite) {
1425 createFileWithData(NonExistantFile, false, fs::CD_CreateNew, "Fizz");
1426 FileRemover Cleanup(NonExistantFile);
1427
1428 int FD;
1429 ASSERT_NO_ERROR(fs::openFileForRead(NonExistantFile, FD));
1430 FileDescriptorCloser Closer(FD);
1431
1432 verifyWrite(FD, "Buzz", false);
1433 verifyRead(FD, "Fizz", true);
1434 }
1435
1436 TEST_F(FileSystemTest, WriteOnlyFileCantRead) {
1437 createFileWithData(NonExistantFile, false, fs::CD_CreateNew, "Fizz");
1438 FileRemover Cleanup(NonExistantFile);
1439
1440 int FD;
1441 ASSERT_NO_ERROR(
1442 fs::openFileForWrite(NonExistantFile, FD, fs::CD_OpenExisting));
1443 FileDescriptorCloser Closer(FD);
1444 verifyRead(FD, "Fizz", false);
1445 verifyWrite(FD, "Buzz", true);
1446 }
1447
1448 TEST_F(FileSystemTest, ReadWriteFileCanReadOrWrite) {
1449 createFileWithData(NonExistantFile, false, fs::CD_CreateNew, "Fizz");
1450 FileRemover Cleanup(NonExistantFile);
1451
1452 int FD;
1453 ASSERT_NO_ERROR(fs::openFileForReadWrite(NonExistantFile, FD,
1454 fs::CD_OpenExisting, fs::OF_None));
1455 FileDescriptorCloser Closer(FD);
1456 verifyRead(FD, "Fizz", true);
1457 verifyWrite(FD, "Buzz", true);
1458 }
1459
12371460 TEST_F(FileSystemTest, set_current_path) {
12381461 SmallString<128> path;
12391462
3030 std::error_code CreateFileWithContent(const SmallString<128> &FilePath,
3131 const StringRef &content) {
3232 int FD = 0;
33 if (std::error_code ec = fs::openFileForWrite(FilePath, FD, fs::F_None))
33 if (std::error_code ec = fs::openFileForWrite(FilePath, FD))
3434 return ec;
3535
3636 const bool ShouldClose = true;
8383 #ifdef LLVM_ON_UNIX
8484 TEST(raw_pwrite_ostreamTest, TestDevNull) {
8585 int FD;
86 sys::fs::openFileForWrite("/dev/null", FD, sys::fs::F_None);
86 sys::fs::openFileForWrite("/dev/null", FD, sys::fs::CD_OpenExisting);
8787 raw_fd_ostream OS(FD, true);
8888 OS << "abcd";
8989 StringRef Test = "test";