summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Support/Unix
diff options
context:
space:
mode:
authorZachary Turner <zturner@google.com>2018-06-07 19:58:58 +0000
committerZachary Turner <zturner@google.com>2018-06-07 19:58:58 +0000
commit1f67a3cba9b09636c56e2109d8a35ae96dc15782 (patch)
treec6ebd0cdd45f18a50b4bee970dc71809b9cb3570 /llvm/lib/Support/Unix
parent84be76133282f8bd66820ca93402a741c0ee632e (diff)
downloadbcm5719-llvm-1f67a3cba9b09636c56e2109d8a35ae96dc15782.tar.gz
bcm5719-llvm-1f67a3cba9b09636c56e2109d8a35ae96dc15782.zip
[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. llvm-svn: 334221
Diffstat (limited to 'llvm/lib/Support/Unix')
-rw-r--r--llvm/lib/Support/Unix/Path.inc125
1 files changed, 81 insertions, 44 deletions
diff --git a/llvm/lib/Support/Unix/Path.inc b/llvm/lib/Support/Unix/Path.inc
index fbfbed66fbc..59d2cb58cf0 100644
--- a/llvm/lib/Support/Unix/Path.inc
+++ b/llvm/lib/Support/Unix/Path.inc
@@ -722,21 +722,69 @@ static bool hasProcSelfFD() {
}
#endif
-std::error_code openFileForRead(const Twine &Name, int &ResultFD,
- SmallVectorImpl<char> *RealPath) {
- SmallString<128> Storage;
- StringRef P = Name.toNullTerminatedStringRef(Storage);
- int OpenFlags = O_RDONLY;
+static int nativeOpenFlags(CreationDisposition Disp, OpenFlags Flags,
+ FileAccess Access) {
+ int Result = 0;
+ if (Access == FA_Read)
+ Result |= O_RDONLY;
+ else if (Access == FA_Write)
+ Result |= O_WRONLY;
+ else if (Access == (FA_Read | FA_Write))
+ Result |= O_RDWR;
+
+ // This is for compatibility with old code that assumed F_Append implied
+ // would open an existing file. See Windows/Path.inc for a longer comment.
+ if (Flags & F_Append)
+ Disp = CD_OpenAlways;
+
+ if (Disp == CD_CreateNew) {
+ Result |= O_CREAT; // Create if it doesn't exist.
+ Result |= O_EXCL; // Fail if it does.
+ } else if (Disp == CD_CreateAlways) {
+ Result |= O_CREAT; // Create if it doesn't exist.
+ Result |= O_TRUNC; // Truncate if it does.
+ } else if (Disp == CD_OpenAlways) {
+ Result |= O_CREAT; // Create if it doesn't exist.
+ } else if (Disp == CD_OpenExisting) {
+ // Nothing special, just don't add O_CREAT and we get these semantics.
+ }
+
+ if (Flags & F_Append)
+ Result |= O_APPEND;
+
#ifdef O_CLOEXEC
- OpenFlags |= O_CLOEXEC;
+ Result |= O_CLOEXEC;
#endif
- if ((ResultFD = sys::RetryAfterSignal(-1, open, P.begin(), OpenFlags)) < 0)
+
+ return Result;
+}
+
+static std::error_code openFile(const Twine &Name, int &ResultFD,
+ CreationDisposition Disp, FileAccess Access,
+ OpenFlags Flags, unsigned Mode) {
+ int OpenFlags = nativeOpenFlags(Disp, Flags, Access);
+
+ SmallString<128> Storage;
+ StringRef P = Name.toNullTerminatedStringRef(Storage);
+ if ((ResultFD = sys::RetryAfterSignal(-1, open, P.begin(), OpenFlags, Mode)) <
+ 0)
return std::error_code(errno, std::generic_category());
#ifndef O_CLOEXEC
int r = fcntl(ResultFD, F_SETFD, FD_CLOEXEC);
(void)r;
assert(r == 0 && "fcntl(F_SETFD, FD_CLOEXEC) failed");
#endif
+ return std::error_code();
+}
+
+std::error_code openFileForRead(const Twine &Name, int &ResultFD,
+ OpenFlags Flags,
+ SmallVectorImpl<char> *RealPath) {
+ std::error_code EC =
+ openFile(Name, ResultFD, CD_OpenExisting, FA_Read, Flags, 0666);
+ if (EC)
+ return EC;
+
// Attempt to get the real name of the file, if the user asked
if(!RealPath)
return std::error_code();
@@ -756,6 +804,9 @@ std::error_code openFileForRead(const Twine &Name, int &ResultFD,
if (CharCount > 0)
RealPath->append(Buffer, Buffer + CharCount);
} else {
+ SmallString<128> Storage;
+ StringRef P = Name.toNullTerminatedStringRef(Storage);
+
// Use ::realpath to get the real path name
if (::realpath(P.begin(), Buffer) != nullptr)
RealPath->append(Buffer, Buffer + strlen(Buffer));
@@ -764,56 +815,42 @@ std::error_code openFileForRead(const Twine &Name, int &ResultFD,
return std::error_code();
}
-Expected<file_t> openNativeFileForRead(const Twine &Name,
+Expected<file_t> openNativeFileForRead(const Twine &Name, OpenFlags Flags,
SmallVectorImpl<char> *RealPath) {
file_t ResultFD;
- std::error_code EC = openFileForRead(Name, ResultFD, RealPath);
+ std::error_code EC = openFileForRead(Name, ResultFD, Flags, RealPath);
if (EC)
return errorCodeToError(EC);
return ResultFD;
}
std::error_code openFileForWrite(const Twine &Name, int &ResultFD,
- sys::fs::OpenFlags Flags, unsigned Mode) {
- // Verify that we don't have both "append" and "excl".
- assert((!(Flags & sys::fs::F_Excl) || !(Flags & sys::fs::F_Append)) &&
- "Cannot specify both 'excl' and 'append' file creation flags!");
-
- int OpenFlags = O_CREAT;
-
-#ifdef O_CLOEXEC
- OpenFlags |= O_CLOEXEC;
-#endif
-
- if (Flags & F_RW)
- OpenFlags |= O_RDWR;
- else
- OpenFlags |= O_WRONLY;
-
- if (Flags & F_Append)
- OpenFlags |= O_APPEND;
- else if (!(Flags & F_NoTrunc))
- OpenFlags |= O_TRUNC;
+ CreationDisposition Disp, OpenFlags Flags,
+ unsigned Mode) {
+ return openFile(Name, ResultFD, Disp, FA_Write, Flags, Mode);
+}
- if (Flags & F_Excl)
- OpenFlags |= O_EXCL;
+Expected<file_t> openNativeFileForWrite(const Twine &Name,
+ CreationDisposition Disp,
+ OpenFlags Flags, unsigned Mode) {
+ file_t ResultFD;
+ std::error_code EC = openFileForWrite(Name, ResultFD, Disp, Flags, Mode);
+ if (EC)
+ return errorCodeToError(EC);
+ return ResultFD;
+}
- SmallString<128> Storage;
- StringRef P = Name.toNullTerminatedStringRef(Storage);
- if ((ResultFD = sys::RetryAfterSignal(-1, open, P.begin(), OpenFlags, Mode)) < 0)
- return std::error_code(errno, std::generic_category());
-#ifndef O_CLOEXEC
- int r = fcntl(ResultFD, F_SETFD, FD_CLOEXEC);
- (void)r;
- assert(r == 0 && "fcntl(F_SETFD, FD_CLOEXEC) failed");
-#endif
- return std::error_code();
+std::error_code openFileForReadWrite(const Twine &Name, int &ResultFD,
+ CreationDisposition Disp, OpenFlags Flags,
+ unsigned Mode) {
+ return openFile(Name, ResultFD, Disp, FA_Read | FA_Write, Flags, Mode);
}
-Expected<file_t> openNativeFileForWrite(const Twine &Name, OpenFlags Flags,
- unsigned Mode) {
+Expected<file_t> openNativeFileForReadWrite(const Twine &Name,
+ CreationDisposition Disp,
+ OpenFlags Flags, unsigned Mode) {
file_t ResultFD;
- std::error_code EC = openFileForWrite(Name, ResultFD, Flags, Mode);
+ std::error_code EC = openFileForReadWrite(Name, ResultFD, Disp, Flags, Mode);
if (EC)
return errorCodeToError(EC);
return ResultFD;
OpenPOWER on IntegriCloud