Skip to content

Commit

Permalink
Merge zopen branch into main (#36)
Browse files Browse the repository at this point in the history
* Add sysmacros.h and chdir_long (#25)

* Add sys/sysmacros.h + chdir_long

* Fix makedev

* Add support for _ENCODE_FILE_NEW + enable man pages (#27)

* Enable V2R5 system builds when targetting V2R4 (#28)

* Workaround for configure issues when building in V2R5+

* fixup

* fixup

* Update zos-v2r5-symbolfixes.h

* Include zos.h rather tha zos-base.h for version information in zos.cc

* Add more v2r5 symbols to include/zos-v2r5-symbolfixes.h (#30)

* Add more v2r5 symbols to include/zos-v2r5-symbolfixes.h

* Update zos-v2r5-symbolfixes.h

* Update zos-v2r5-symbolfixes.h with more functions (#31)

* Update __threading_support

* Carry over fixes from internal main branch

* Fix fopen_ascii for untagged files (#32)

* Add __getprogramdir, getprogname, getloadavg (#33)

* Add getloadavg

* Add getprogname and __getprogramdir

* Add getprogname and __getprogramdir

* Fix comment in getloadvg

* Add details for how to find CCT offsets/descriptions

* Fix typo

* Update zos-v2r5-symbolfixes.h (#34)

Add shm_open to the list

* Remove dupe bfdcache_destroyed

* Fix style and indention in zos-io.cc

* Rename program info tests + misc fixes

* Rename test-new-programinfo.cc to test-programinfo.cc
  • Loading branch information
IgorTodorovskiIBM authored Dec 3, 2023
1 parent 67caca0 commit cfd28b0
Show file tree
Hide file tree
Showing 15 changed files with 337 additions and 27 deletions.
1 change: 1 addition & 0 deletions include/c++/v1/__threading_support
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

//TODO(itodorov) - zos: workaround for nanosleep WoZ conflict, revisit
// once WoZ allow overriding or LE provides a nanosleep definition
#include <time.h>
#define nanosleep cpp_nanosleep
#include_next <__threading_support>
#undef nanosleep
Expand Down
16 changes: 14 additions & 2 deletions include/stdlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,23 @@ extern "C" {
* Replace getenv with the ascii implementation of __getenv (@@A00423)
which copies pointer to a buffer and is retained even after the environment changes
*/
__Z_EXPORT char* getenv(const char*) asm("@@A00423");

__Z_EXPORT char* getenv(const char*) __asm("@@A00423");
#if defined(__cplusplus)
}
#endif
#endif

#if defined(__cplusplus)
extern "C" {
#endif
/**
* C Lib functions that do not conflict with z/OS LE
*/
__Z_EXPORT char *mkdtemp(char *templ);
__Z_EXPORT int getloadavg(double loadavg[], int nelem);
__Z_EXPORT const char * getprogname(void);
#if defined(__cplusplus)
}
#endif

#endif
16 changes: 16 additions & 0 deletions include/sys/sysmacros.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
///////////////////////////////////////////////////////////////////////////////
// Licensed Materials - Property of IBM
// ZOSLIB
// (C) Copyright IBM Corp. 2021. All Rights Reserved.
// US Government Users Restricted Rights - Use, duplication
// or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
///////////////////////////////////////////////////////////////////////////////

#ifndef ZOS_SYSMACROS_H_
#define ZOS_SYSMACROS_H_

#define major(x) (((unsigned)(x) >> 8) & 0x7f)
#define minor(x) ((x) & 0xff)
#define makedev(x, y) (unsigned short)(((x) << 8) | ((y) & 0xff))

#endif
5 changes: 5 additions & 0 deletions include/zos-base.h
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,11 @@ __Z_EXPORT bool __doLogMemoryWarning();
*/
__Z_EXPORT void __mainTerminating();

/**
* Returns the program's directory as an absolute path
*/
__Z_EXPORT char* __getprogramdir();

#ifdef __cplusplus
}
#endif
Expand Down
14 changes: 12 additions & 2 deletions include/zos-sys-info.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,16 @@ typedef enum {

// CPU Management Control Table (CCT).
typedef struct ZOSCCT {
uint8_t filler[110];
uint16_t cpuCount; // Number of online CPUs.
// Field offsets described in SYS1.MODGEN(IRACCT)
// Field descriptions provided in https://www.ibm.com/docs/en/zos/3.1.0?topic=ttar-contents-report
uint8_t filler1[72]; // 0:72 Ignore fields not relevant to current implementation
uint32_t ccvrbswt; // Recent base system wait time
uint8_t filler2[4]; // Ignore fields not relevant to current implementation
uint32_t ccvrbstd; // Recent base time of day
uint8_t filler3[18]; // 84:18 Ignore fields not relevant to current implementation
uint16_t ccvutilp; // System CPU utilization
uint8_t filler4[6]; // 104:6 Ignore fields not relevant to current implementation
uint16_t cpuCount; // Number of online CPUs.
} ZOSCCT_t;

// System Resources Manager Control Table (RMCT).
Expand Down Expand Up @@ -146,6 +154,8 @@ __Z_EXPORT bool __is_vef1_available();
*/
__Z_EXPORT char *__get_cpu_model(char *buffer, size_t size);

__Z_EXPORT int getloadavg(double loadavg[], int nelem);

#ifdef __cplusplus
}
#endif
Expand Down
51 changes: 51 additions & 0 deletions include/zos-v2r5-symbolfixes.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
///////////////////////////////////////////////////////////////////////////////
// ZOSLIB
// (C) Copyright IBM Corp. 2023. All Rights Reserved.
// US Government Users Restricted Rights - Use, duplication
// or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
///////////////////////////////////////////////////////////////////////////////

#ifndef ZOS_V2R5_SYMBOLFIXES_H
#define ZOS_V2R5_SYMBOLFIXES_H

// This enables builds on >=V2R5 systems when the target is <V2R5
// Redefines >=V2R5 symbols with _undefined suffix to trigger a linker
// error so they are not detected by configure scripts
#if (__TARGET_LIB__ < 0x42050000)
#pragma redefine_extname readlinkat readlinkat_undefined
#pragma redefine_extname openat openat_undefined
#pragma redefine_extname linkat linkat_undefined
#pragma redefine_extname faccessat faccessat_undefined
#pragma redefine_extname fstatat fstatat_undefined
#pragma redefine_extname unlinkat unlinkat_undefined
#pragma redefine_extname symlinkat symlinkat_undefined
#pragma redefine_extname renameat rename_undefined
#pragma redefine_extname getrandom getrandom_undefined
#pragma redefine_extname pipe2 pipe2_undefined
#pragma redefine_extname fsstatfs fsstatfs_undefined
#pragma redefine_extname getline getline_undefined
#pragma redefine_extname dprintf dprintf_undefined
#pragma redefine_extname dirfd dirfd_undefined
#pragma redefine_extname fchmodat fchmodat_undefined
#pragma redefine_extname mkdirat mkdirat_undefined
#pragma redefine_extname mkfifoat mkfifoat_undefined
#pragma redefine_extname mknodat mknodat_undefined
#pragma redefine_extname renameat2 renameat2_undefined
#pragma redefine_extname futimesat futimesat_undefined
#pragma redefine_extname fchownat fchownat_undefined
#pragma redefine_extname strchrnul strchrnul_undefined
#pragma redefine_extname sethostname sethostname_undefined
#pragma redefine_extname syncfs syncfs_undefined
#pragma redefine_extname sysinfo sysinfo_undefined
#pragma redefine_extname fdatasync fdatasync_undefined
#pragma redefine_extname inotify_init inotify_init_undefined
#pragma redefine_extname prctl prctl_undefined
#pragma redefine_extname fstatfs fstatfs_undefined
#pragma redefine_extname setresuid setresuid_undefined
#pragma redefine_extname setresgid setresgid_undefined
#pragma redefine_extname dup3 dup3_undefined
#pragma redefine_extname flock flock_undefined
#pragma redefine_extname shm_open shm_open_undefined
#endif

#endif // ZOS_V2R5_SYMBOLFIXES_H
2 changes: 1 addition & 1 deletion man/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@ add_custom_command(


# Define the install rule for the man page
#install(FILES "${MAN_OUTPUT_DIR}/${INPUT_FILE}" DESTINATION "${CMAKE_INSTALL_PREFIX}/share/man/man1")
install(FILES "${CMAKE_SOURCE_DIR}/man/${INPUT_FILE}" DESTINATION "share/man/man1")
26 changes: 17 additions & 9 deletions man/zoslib.1
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.TH ZOSLIB 1 "February 2023" "ZOSLIB"
.TH ZOSLIB 1 "September 2023" "ZOSLIB"

.SH NAME
zoslib \- a z/OS C/C++ library
Expand All @@ -12,16 +12,16 @@ ZOSLIB is a z/OS C/C++ library. It is an extended implementation of the z/OS LE
Specify the CCSID for the stdio file descriptors. If these environment variables are not set and if the stdio file descriptor represents an untagged tty, it will be set to 1047 by default.

.TP
.B __MEMORY_USAGE_LOG_LEVEL
set to 1 to display only warnings when memory is allocated or freed, and 2 to display all messages; the process started/terminated messages that include memory stats summary, as well as any error messages
.B _ENCODE_FILE_NEW=ISO8859-1
(Default) New files are created with encoding ISO8859-1 and tagged ISO8859-1.

.TP
.B __MEMORY_USAGE_LOG_FILE
name of the log file associated with __MEMORY_USAGE_LOG_LEVEL, including 'stdout' and 'stderr', to which diagnostic messages for memory allocation and release are to be written
.B _ENCODE_FILE_NEW=IBM-1047
New files are created with encoding IBM-1047 and tagged IBM-1047.

.TP
.B __RUNDEBUG
set to toggle debug ZOSLIB mode
.B _ENCODE_FILE_NEW=BINARY
New files are created without translation and are tagged as BINARY.

.TP
.B __UNTAGGED_READ_MODE=AUTO
Expand All @@ -44,8 +44,16 @@ for no explicit conversion of data
for same behavior as "AUTO" but issue a warning if conversion occurs

.TP
.B __IPC_CLEANUP
set to toggle IPC cleanup at startup
.B __MEMORY_USAGE_LOG_LEVEL
set to 1 to display only warnings when memory is allocated or freed, and 2 to display all messages; the process started/terminated messages that include memory stats summary, as well as any error messages

.TP
.B __MEMORY_USAGE_LOG_FILE
name of the log file associated with __MEMORY_USAGE_LOG_LEVEL, including 'stdout' and 'stderr', to which diagnostic messages for memory allocation and release are to be written

.TP
.B __RUNDEBUG
set to toggle debug ZOSLIB mode

.SH EXAMPLES
To set the __UNTAGGED_READ_MODE environment variable to STRICT and disable explicit conversion of data:
Expand Down
5 changes: 3 additions & 2 deletions src/zos-char-util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <string.h>
#include <sys/stat.h>
#include <unordered_map>
#include <pthread.h>

#ifdef __cplusplus
extern "C" {
Expand Down Expand Up @@ -446,12 +447,12 @@ struct IntHash {

typedef unsigned long fd_attribute;

typedef std::unordered_map<int, fd_attribute, IntHash>::const_iterator cursor_t;

// [[clang::no_destroy]] attribute can be set for this, but the attribute is
// not available for xlclang.
static bool bfdcache_destroyed = false;

typedef std::unordered_map<int, fd_attribute, IntHash>::const_iterator cursor_t;

class fdAttributeCache {
std::unordered_map<int, fd_attribute, IntHash> cache;
pthread_mutex_t access_lock;
Expand Down
66 changes: 55 additions & 11 deletions src/zos-io.cc
Original file line number Diff line number Diff line change
Expand Up @@ -702,6 +702,23 @@ int __disableautocvt(int fd) {
return fcntl(fd, F_CONTROL_CVT, &req);
}

int __tag_new_file(int fd) {
char* encode_file_new = getenv("_ENCODE_FILE_NEW");

int ccsid = 819;

if (encode_file_new) {
if (strcmp(encode_file_new, "IBM-1047") == 0) {
ccsid = 1047;
} else if (strcmp(encode_file_new, "BINARY") == 0) {
// Set the file descriptor to binary mode
return __setfdbinary(fd);
}
}

return __chgfdccsid(fd, ccsid);
}

int __chgfdcodeset(int fd, char* codeset) {
unsigned short ccsid = __toCcsid(codeset);
if (!ccsid)
Expand Down Expand Up @@ -808,9 +825,9 @@ int __open_ascii(const char *filename, int opts, ...) {
if (fd >= 0) {
// Tag new files as ASCII (819)
if (is_new_file) {
__chgfdccsid(fd, 819);
/* Calling __chgfdccsid() should not clobber errno. */
errno = old_errno;
__tag_new_file(fd);
/* Calling __tag_new_file() should not clobber errno. */
errno = old_errno;
}
// Enable auto-conversion of untagged files
else if (S_ISREG(sb.st_mode)) {
Expand Down Expand Up @@ -852,22 +869,20 @@ FILE *__fopen_ascii(const char *filename, const char *mode) {
if (fp) {
int fd = fileno(fp);
if (is_new_file) {
__chgfdccsid(fd, 819);
errno = old_errno;
__tag_new_file(fd);
errno = old_errno;
}
// Enable auto-conversion of untagged files
else if (S_ISREG(sb.st_mode)) {
struct file_tag *t = &sb.st_tag;
if (t->ft_txtflag == 0 && (t->ft_ccsid == 0 || t->ft_ccsid == 1047) &&
strcmp(mode, "r") == 0) {
__disableautocvt(fd); // disable z/OS autocvt on untagged file and use our heuristic
if (__file_needs_conversion_init(filename, fd)) {
struct f_cnvrt cvtreq = {SETCVTON, 0, 1047};
fcntl(fd, F_CONTROL_CVT, &cvtreq);
/* Calling fcntl() should not clobber errno. */
errno = old_errno;
} else {
// fopen tags untagged files, which enables auto-conversion
__disableautocvt(fd);
}
}
} else if (isatty(fd)) {
Expand Down Expand Up @@ -910,13 +925,42 @@ int __mkstemp_ascii(char * tmpl) {
if (ret < 0)
return ret;

// Default ccsid for new fds should be ASCII (819)
if (__chgfdccsid(ret, 819) != 0)
return -1;
__tag_new_file(ret);

return ret;
}

char *mkdtemp(char *templ) {
size_t len = strlen(templ);
int retries = 10; // Number of retries to generate a unique directory name

// Check that the templ ends with "XXXXXX" as required
if (len < 6 || strcmp(templ + len - 6, "XXXXXX") != 0) {
errno = EINVAL;
return NULL;
}

while (retries--) {
// Generate a random string to replace "XXXXXX" in the templ
for (size_t i = len - 6; i < len; i++) {
templ[i] = 'a' + rand() % 26;
}

// Attempt to create the directory
if (mkdir(templ, 0700) == 0) {
return templ;
}

// If mkdir failed, check if it was due to a collision with an existing directory
if (errno != EEXIST) {
return NULL;
}
}

// If all retries fail, return NULL
return NULL;
}

int __close(int fd) {
int ret = __close_orig(fd);
if (ret < 0)
Expand Down
16 changes: 16 additions & 0 deletions src/zos-sys-info.cc
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,22 @@ int __get_num_frames(void) {
return static_cast<int>(rce->pool);
}

// Adapted from OMR codebase: https://github.com/eclipse/omr/blob/master/port/unix/omrsysinfo.c#L4629
int getloadavg(double loadavg[], int nelem) {
if (nelem > 3 || nelem <= 0)
return -1;

ZOSCVT* __ptr32 cvt = ((ZOSPSA*)0)->cvt;
ZOSRMCT* __ptr32 rcmt = cvt->rmct;
ZOSCCT* __ptr32 cct = rcmt->cct;

//Hack: z/OS does not get cpu load in samples, just use the same value
for (int i = 0; i < nelem; i++)
loadavg[i] = (double)cct->ccvutilp / 100.0;

return nelem;
}

oslvl_t __get_os_level(void) {
static oslvl_t oslvl = ZOSLVL_UNKNOWN;
if (oslvl != ZOSLVL_UNKNOWN)
Expand Down
Loading

0 comments on commit cfd28b0

Please sign in to comment.