Skip to content

Commit 244ad16

Browse files
committed
Query if a file is text and set the text flag accordingly
1 parent 6d216fb commit 244ad16

File tree

3 files changed

+41
-1
lines changed

3 files changed

+41
-1
lines changed

llvm/include/llvm/Support/AutoConvert.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@ std::error_code restorezOSStdHandleAutoConversion(int FD);
5252
/// \brief Set the tag information for a file descriptor.
5353
std::error_code setzOSFileTag(int FD, int CCSID, bool Text);
5454

55+
// Get the the tag ccsid for a file name or a file descriptor.
56+
ErrorOr<__ccsid_t> getzOSFileTag(const char *FileName, const int FD = -1);
57+
58+
// Query the file tag to determine if the file is a text file.
59+
ErrorOr<bool> iszOSTextFile(const char *Filename, const int FD = -1);
60+
5561
} // namespace llvm
5662
#endif // __cplusplus
5763

llvm/lib/Support/AutoConvert.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,4 +116,30 @@ std::error_code llvm::setzOSFileTag(int FD, int CCSID, bool Text) {
116116
return std::error_code();
117117
}
118118

119+
ErrorOr<__ccsid_t> llvm::getzOSFileTag(const char *FileName, const int FD) {
120+
// If we have a file descriptor, use it to find out file tagging. Otherwise we
121+
// need to use stat() with the file path.
122+
if (FD != -1) {
123+
struct f_cnvrt Query = {
124+
QUERYCVT, // cvtcmd
125+
0, // pccsid
126+
0, // fccsid
127+
};
128+
if (fcntl(FD, F_CONTROL_CVT, &Query) == -1)
129+
return std::error_code(errno, std::generic_category());
130+
return Query.fccsid;
131+
}
132+
struct stat Attr;
133+
if (stat(FileName, &Attr) == -1)
134+
return std::error_code(errno, std::generic_category());
135+
return Attr.st_tag.ft_ccsid;
136+
}
137+
138+
ErrorOr<bool> llvm::iszOSTextFile(const char *Filename, const int FD) {
139+
ErrorOr<__ccsid_t> Ccsid = getzOSFileTag(Filename, FD);
140+
if (std::error_code EC = Ccsid.getError())
141+
return EC;
142+
return *Ccsid != FT_BINARY;
143+
}
144+
119145
#endif // __MVS__

llvm/lib/Support/VirtualFileSystem.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,8 +325,16 @@ ErrorOr<Status> RealFileSystem::status(const Twine &Path) {
325325
ErrorOr<std::unique_ptr<File>>
326326
RealFileSystem::openFileForRead(const Twine &Name) {
327327
SmallString<256> RealName, Storage;
328+
auto OpenFlags = sys::fs::OF_None;
329+
#ifdef __MVS__
330+
// If the file is tagged with a text ccsid, it may require autoconversion.
331+
llvm::ErrorOr<bool> IsFileText =
332+
llvm::iszOSTextFile(Name.str().c_str());
333+
if (IsFileText && *IsFileText)
334+
OpenFlags |= sys::fs::OF_Text;
335+
#endif
328336
Expected<file_t> FDOrErr = sys::fs::openNativeFileForRead(
329-
adjustPath(Name, Storage), sys::fs::OF_None, &RealName);
337+
adjustPath(Name, Storage), OpenFlags, &RealName);
330338
if (!FDOrErr)
331339
return errorToErrorCode(FDOrErr.takeError());
332340
return std::unique_ptr<File>(

0 commit comments

Comments
 (0)