11527a5e4SAbhina Sreeskantharajan //===- AutoConvert.cpp - Auto conversion between ASCII/EBCDIC -------------===// 21527a5e4SAbhina Sreeskantharajan // 31527a5e4SAbhina Sreeskantharajan // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 41527a5e4SAbhina Sreeskantharajan // See https://llvm.org/LICENSE.txt for license information. 51527a5e4SAbhina Sreeskantharajan // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 61527a5e4SAbhina Sreeskantharajan // 71527a5e4SAbhina Sreeskantharajan //===----------------------------------------------------------------------===// 81527a5e4SAbhina Sreeskantharajan // 91527a5e4SAbhina Sreeskantharajan // This file contains functions used for auto conversion between 101527a5e4SAbhina Sreeskantharajan // ASCII/EBCDIC codepages specific to z/OS. 111527a5e4SAbhina Sreeskantharajan // 121527a5e4SAbhina Sreeskantharajan //===----------------------------------------------------------------------===// 131527a5e4SAbhina Sreeskantharajan 141527a5e4SAbhina Sreeskantharajan #ifdef __MVS__ 151527a5e4SAbhina Sreeskantharajan 161527a5e4SAbhina Sreeskantharajan #include "llvm/Support/AutoConvert.h" 170fe271c3SFanbo Meng #include "llvm/Support/Error.h" 18ab380c28SAbhina Sree #include <cassert> 191527a5e4SAbhina Sreeskantharajan #include <fcntl.h> 201527a5e4SAbhina Sreeskantharajan #include <sys/stat.h> 21ab380c28SAbhina Sree #include <unistd.h> 221527a5e4SAbhina Sreeskantharajan 23*04379c98SAbhina Sree using namespace llvm; 24*04379c98SAbhina Sree 25ab380c28SAbhina Sree static int savedStdHandleAutoConversionMode[3] = {-1, -1, -1}; 26ab380c28SAbhina Sree 27311ac638SAbhina Sree int disablezOSAutoConversion(int FD) { 281527a5e4SAbhina Sreeskantharajan static const struct f_cnvrt Convert = { 291527a5e4SAbhina Sreeskantharajan SETCVTOFF, // cvtcmd 301527a5e4SAbhina Sreeskantharajan 0, // pccsid 31ab380c28SAbhina Sree 0, // fccsid 321527a5e4SAbhina Sreeskantharajan }; 33ab380c28SAbhina Sree 34ab380c28SAbhina Sree return fcntl(FD, F_CONTROL_CVT, &Convert); 351527a5e4SAbhina Sreeskantharajan } 361527a5e4SAbhina Sreeskantharajan 37311ac638SAbhina Sree int restorezOSStdHandleAutoConversion(int FD) { 38ab380c28SAbhina Sree assert(FD == STDIN_FILENO || FD == STDOUT_FILENO || FD == STDERR_FILENO); 39ab380c28SAbhina Sree if (savedStdHandleAutoConversionMode[FD] == -1) 40ab380c28SAbhina Sree return 0; 41ab380c28SAbhina Sree struct f_cnvrt Cvt = { 42ab380c28SAbhina Sree savedStdHandleAutoConversionMode[FD], // cvtcmd 43ab380c28SAbhina Sree 0, // pccsid 44ab380c28SAbhina Sree 0, // fccsid 45ab380c28SAbhina Sree }; 46ab380c28SAbhina Sree return (fcntl(FD, F_CONTROL_CVT, &Cvt)); 47ab380c28SAbhina Sree } 48ab380c28SAbhina Sree 49311ac638SAbhina Sree int enablezOSAutoConversion(int FD) { 501527a5e4SAbhina Sreeskantharajan struct f_cnvrt Query = { 511527a5e4SAbhina Sreeskantharajan QUERYCVT, // cvtcmd 521527a5e4SAbhina Sreeskantharajan 0, // pccsid 531527a5e4SAbhina Sreeskantharajan 0, // fccsid 541527a5e4SAbhina Sreeskantharajan }; 551527a5e4SAbhina Sreeskantharajan 561527a5e4SAbhina Sreeskantharajan if (fcntl(FD, F_CONTROL_CVT, &Query) == -1) 57ab380c28SAbhina Sree return -1; 581527a5e4SAbhina Sreeskantharajan 59ab380c28SAbhina Sree // We don't need conversion for UTF-8 tagged files. 60ab380c28SAbhina Sree // TODO: Remove the assumption of ISO8859-1 = UTF-8 here when we fully resolve 61ab380c28SAbhina Sree // problems related to UTF-8 tagged source files. 62ab380c28SAbhina Sree // When the pccsid is not ISO8859-1, autoconversion is still needed. 63ab380c28SAbhina Sree if (Query.pccsid == CCSID_ISO8859_1 && 64ab380c28SAbhina Sree (Query.fccsid == CCSID_UTF_8 || Query.fccsid == CCSID_ISO8859_1)) 65ab380c28SAbhina Sree return 0; 66ab380c28SAbhina Sree 67ab380c28SAbhina Sree // Save the state of std handles before we make changes to it. 68ab380c28SAbhina Sree if ((FD == STDIN_FILENO || FD == STDOUT_FILENO || FD == STDERR_FILENO) && 69ab380c28SAbhina Sree savedStdHandleAutoConversionMode[FD] == -1) 70ab380c28SAbhina Sree savedStdHandleAutoConversionMode[FD] = Query.cvtcmd; 71ab380c28SAbhina Sree 72ab380c28SAbhina Sree if (FD == STDOUT_FILENO || FD == STDERR_FILENO) 73ab380c28SAbhina Sree Query.cvtcmd = SETCVTON; 74ab380c28SAbhina Sree else 751527a5e4SAbhina Sreeskantharajan Query.cvtcmd = SETCVTALL; 76ab380c28SAbhina Sree 771527a5e4SAbhina Sreeskantharajan Query.pccsid = 781527a5e4SAbhina Sreeskantharajan (FD == STDIN_FILENO || FD == STDOUT_FILENO || FD == STDERR_FILENO) 791527a5e4SAbhina Sreeskantharajan ? 0 801527a5e4SAbhina Sreeskantharajan : CCSID_UTF_8; 811527a5e4SAbhina Sreeskantharajan // Assume untagged files to be IBM-1047 encoded. 821527a5e4SAbhina Sreeskantharajan Query.fccsid = (Query.fccsid == FT_UNTAGGED) ? CCSID_IBM_1047 : Query.fccsid; 83ab380c28SAbhina Sree return fcntl(FD, F_CONTROL_CVT, &Query); 84ab380c28SAbhina Sree } 85ab380c28SAbhina Sree 86311ac638SAbhina Sree std::error_code llvm::disablezOSAutoConversion(int FD) { 87311ac638SAbhina Sree if (::disablezOSAutoConversion(FD) == -1) 88ba13fa2aSMichael Spencer return errnoAsErrorCode(); 89ab380c28SAbhina Sree 90ab380c28SAbhina Sree return std::error_code(); 91ab380c28SAbhina Sree } 92ab380c28SAbhina Sree 93311ac638SAbhina Sree std::error_code llvm::enablezOSAutoConversion(int FD) { 94311ac638SAbhina Sree if (::enablezOSAutoConversion(FD) == -1) 95ba13fa2aSMichael Spencer return errnoAsErrorCode(); 96ab380c28SAbhina Sree 97ab380c28SAbhina Sree return std::error_code(); 98ab380c28SAbhina Sree } 99ab380c28SAbhina Sree 100311ac638SAbhina Sree std::error_code llvm::restorezOSStdHandleAutoConversion(int FD) { 101311ac638SAbhina Sree if (::restorezOSStdHandleAutoConversion(FD) == -1) 102ba13fa2aSMichael Spencer return errnoAsErrorCode(); 103ab380c28SAbhina Sree 1046a128750SAbhina Sreeskantharajan return std::error_code(); 1051527a5e4SAbhina Sreeskantharajan } 1061527a5e4SAbhina Sreeskantharajan 107311ac638SAbhina Sree std::error_code llvm::setzOSFileTag(int FD, int CCSID, bool Text) { 1081527a5e4SAbhina Sreeskantharajan assert((!Text || (CCSID != FT_UNTAGGED && CCSID != FT_BINARY)) && 1091527a5e4SAbhina Sreeskantharajan "FT_UNTAGGED and FT_BINARY are not allowed for text files"); 1101527a5e4SAbhina Sreeskantharajan struct file_tag Tag; 1111527a5e4SAbhina Sreeskantharajan Tag.ft_ccsid = CCSID; 1121527a5e4SAbhina Sreeskantharajan Tag.ft_txtflag = Text; 1131527a5e4SAbhina Sreeskantharajan Tag.ft_deferred = 0; 1141527a5e4SAbhina Sreeskantharajan Tag.ft_rsvflags = 0; 1151527a5e4SAbhina Sreeskantharajan 1166a128750SAbhina Sreeskantharajan if (fcntl(FD, F_SETTAG, &Tag) == -1) 117ba13fa2aSMichael Spencer return errnoAsErrorCode(); 1186a128750SAbhina Sreeskantharajan return std::error_code(); 1191527a5e4SAbhina Sreeskantharajan } 1201527a5e4SAbhina Sreeskantharajan 121*04379c98SAbhina Sree ErrorOr<__ccsid_t> llvm::getzOSFileTag(const char *FileName, const int FD) { 122*04379c98SAbhina Sree // If we have a file descriptor, use it to find out file tagging. Otherwise we 123*04379c98SAbhina Sree // need to use stat() with the file path. 124*04379c98SAbhina Sree if (FD != -1) { 125*04379c98SAbhina Sree struct f_cnvrt Query = { 126*04379c98SAbhina Sree QUERYCVT, // cvtcmd 127*04379c98SAbhina Sree 0, // pccsid 128*04379c98SAbhina Sree 0, // fccsid 129*04379c98SAbhina Sree }; 130*04379c98SAbhina Sree if (fcntl(FD, F_CONTROL_CVT, &Query) == -1) 131*04379c98SAbhina Sree return std::error_code(errno, std::generic_category()); 132*04379c98SAbhina Sree return Query.fccsid; 133*04379c98SAbhina Sree } 134*04379c98SAbhina Sree struct stat Attr; 135*04379c98SAbhina Sree if (stat(FileName, &Attr) == -1) 136*04379c98SAbhina Sree return std::error_code(errno, std::generic_category()); 137*04379c98SAbhina Sree return Attr.st_tag.ft_ccsid; 138*04379c98SAbhina Sree } 139*04379c98SAbhina Sree 140*04379c98SAbhina Sree ErrorOr<bool> llvm::needzOSConversion(const char *FileName, const int FD) { 141*04379c98SAbhina Sree ErrorOr<__ccsid_t> Ccsid = getzOSFileTag(FileName, FD); 142*04379c98SAbhina Sree if (std::error_code EC = Ccsid.getError()) 143*04379c98SAbhina Sree return EC; 144*04379c98SAbhina Sree // We don't need conversion for UTF-8 tagged files or binary files. 145*04379c98SAbhina Sree // TODO: Remove the assumption of ISO8859-1 = UTF-8 here when we fully resolve 146*04379c98SAbhina Sree // problems related to UTF-8 tagged source files. 147*04379c98SAbhina Sree switch (*Ccsid) { 148*04379c98SAbhina Sree case CCSID_UTF_8: 149*04379c98SAbhina Sree case CCSID_ISO8859_1: 150*04379c98SAbhina Sree case FT_BINARY: 151*04379c98SAbhina Sree return false; 152*04379c98SAbhina Sree default: 153*04379c98SAbhina Sree return true; 154*04379c98SAbhina Sree } 155*04379c98SAbhina Sree } 156*04379c98SAbhina Sree 1571527a5e4SAbhina Sreeskantharajan #endif //__MVS__ 158