Split openFileForWrite into windows and unix versions.

It is similar to 186511, but for creating files for writing.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@186679 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Rafael Espindola 2013-07-19 15:02:03 +00:00
parent c9c9825c93
commit b1a003f377
4 changed files with 92 additions and 30 deletions

View File

@ -692,36 +692,6 @@ error_code createUniqueDirectory(const Twine &Prefix,
true, 0, FS_Dir);
}
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_WRONLY | O_CREAT;
#ifdef O_BINARY
if (Flags & F_Binary)
OpenFlags |= O_BINARY;
#endif
if (Flags & F_Append)
OpenFlags |= O_APPEND;
else
OpenFlags |= O_TRUNC;
if (Flags & F_Excl)
OpenFlags |= O_EXCL;
SmallString<128> Storage;
StringRef P = Name.toNullTerminatedStringRef(Storage);
while ((ResultFD = open(P.begin(), OpenFlags, Mode)) < 0) {
if (errno != EINTR)
return error_code(errno, system_category());
}
return error_code::success();
}
error_code make_absolute(SmallVectorImpl<char> &path) {
StringRef p(path.data(), path.size());

View File

@ -766,6 +766,31 @@ error_code openFileForRead(const Twine &Name, int &ResultFD) {
return error_code::success();
}
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_WRONLY | O_CREAT;
if (Flags & F_Append)
OpenFlags |= O_APPEND;
else
OpenFlags |= O_TRUNC;
if (Flags & F_Excl)
OpenFlags |= O_EXCL;
SmallString<128> Storage;
StringRef P = Name.toNullTerminatedStringRef(Storage);
while ((ResultFD = open(P.begin(), OpenFlags, Mode)) < 0) {
if (errno != EINTR)
return error_code(errno, system_category());
}
return error_code::success();
}
} // end namespace fs
} // end namespace sys
} // end namespace llvm

View File

@ -1071,6 +1071,60 @@ error_code openFileForRead(const Twine &Name, int &ResultFD) {
return error_code::success();
}
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!");
SmallString<128> PathStorage;
SmallVector<wchar_t, 128> PathUTF16;
if (error_code EC = UTF8ToUTF16(Name.toStringRef(PathStorage),
PathUTF16))
return EC;
DWORD CreationDisposition;
if (Flags & F_Excl)
CreationDisposition = CREATE_NEW;
else if (Flags & F_Append)
CreationDisposition = OPEN_ALWAYS;
else
CreationDisposition = CREATE_ALWAYS;
HANDLE H = ::CreateFileW(PathUTF16.begin(), GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
CreationDisposition, FILE_ATTRIBUTE_NORMAL, NULL);
if (H == INVALID_HANDLE_VALUE) {
error_code EC = windows_error(::GetLastError());
// Provide a better error message when trying to open directories.
// This only runs if we failed to open the file, so there is probably
// no performances issues.
if (EC != windows_error::access_denied)
return EC;
if (is_directory(Name))
return error_code(errc::is_a_directory, posix_category());
return EC;
}
int OpenFlags = 0;
if (Flags & F_Append)
OpenFlags |= _O_APPEND;
if (!(Flags & F_Binary))
OpenFlags |= _O_TEXT;
int FD = ::_open_osfhandle(intptr_t(H), OpenFlags);
if (FD == -1) {
::CloseHandle(H);
return windows_error::invalid_handle;
}
ResultFD = FD;
return error_code::success();
}
} // end namespace fs
} // end namespace sys
} // end namespace llvm

View File

@ -0,0 +1,13 @@
REQUIRES: shell
RUN: mkdir -p %t
RUN: cd %t
RUN: rm -rf foo
RUN: echo foo > foo
RUN: rm -f test.a
RUN: llvm-ar rc test.a foo
RUN: rm foo
RUN: mkdir foo
RUN: not llvm-ar x test.a foo 2>&1 | FileCheck %s
CHECK: foo: Is a directory