def dscb1data_from_dsname_and_volser(dsname, volser, debug=False, svc_args=None, encoding=None): if svc_args is None: svc_args = bytearray(5 * 8) if encoding is None: dsname = codecs.encode("{:44s}".format(dsname), encoding=cp1047_oe) volser = codecs.encode("{:6s}".format(volser), encoding=cp1047_oe) obtain_search = bytearray_set_address_size( bytearray(4 + 4 + 4 + 4 + 44 + 6 + 140), 31) struct.pack_into( '=IIII' + '44s6s', obtain_search, 0, 0xC1000000 + 0x801, # CAMLST_SEARCH + CAMLST_EADSCB_OK bytearray_buffer_address(obtain_search) + 4 * 4, bytearray_buffer_address(obtain_search) + 4 * 4 + 44, bytearray_buffer_address(obtain_search) + 4 * 4 + 44 + 6, dsname, volser) struct.pack_into('QQQQQ', svc_args, 0, 0, 0, bytearray_buffer_address(obtain_search), 27, SYSTEM_CALL__SVC) # CAMLST OBTAIN zos_system_call(svc_args) rc = struct.unpack_from('=4xI', svc_args, 0)[0] if rc != 0: raise OSError("CAMLIST SEARCH returned rc=0x%X" % (rc, )) if debug: print( dump_region( bytearray_buffer_address(obtain_search) + 4 * 4 + 44 + 6, 140)) return (obtain_search, 4 * 4 + 44 + 6)
def build_a24(self, ddname): self.a24 = bytearray_set_address_size(bytearray(a24_size), 24) a24 = self.a24 struct.paueck_into('HHHHHHHHHHHHHHHHH', a24, abend_exit_offset, 0x5870, 0x1004, # L R7,4(,R1) # R7 is the DCB 0x9104, 0x1003, # TM 3(R1),X'04' # is it ignorable? 0x4770, 0xF012, # BNZ *+10 0x9200, 0x1003, # MVI 3(R1),X'00' # if we can't ignore, allow it to abend 0x07FE, # BR R14 # return 0x9204, 0x1003, # MVI 3(R1),X'04' # ignore it 0xA77A, 0xFFFF & -dcb_offset, # AHI R7,xxxx 0xD203, 0x7000, 0x1000, # MVC 0(R7),0(R1) 0x07FE) # BR R14 # return struct.pack_into('I', a24, exit_list_offset, ((0x80 + 0x11)<<24) + (bytearray_buffer_address(a24) + abend_exit_offset)) # DCB DSORG=PO,MACRF=R for i in (0x17, 0x1F, 0x23, 0x37, 0x3B, 0x47, 0x4B, 0x4F, 0x57): a24[dcb_offset + i] = 0x01 a24[dcb_offset + 0x1A] = 0x02 a24[dcb_offset + 0x30] = 0x02 a24[dcb_offset + 0x32] = 0x24 struct.pack_into("8s", a24, dcb_offset + 0x28, codecs.encode("{:8s}".format(ddname), encoding=cp1047_oe)) exit_list_address = bytearray(4) struct.pack_into('I', exit_list_address, 0, bytearray_buffer_address(a24) + exit_list_offset) struct.pack_into("3s", a24, dcb_offset + 0x35, exit_list_address[1:])
def close(self): # CLOSE (MYDCB),MODE=31 a24 = self.a24 bldl_list = self.bldl_list close_args = bytearray_set_address_size(bytearray(8), 31) struct.pack_into('=B3xI', close_args, 0, 0x80, bytearray_buffer_address(a24) + dcb_offset) struct.pack_into('QQQQQ', self.svc_args, 0, 0, bytearray_buffer_address(close_args), 0, 20, SYSTEM_CALL__SVC) zos_system_call(self.svc_args) rc = struct.unpack_from('Q', self.svc_args, 0)
def load(name): name_buffer = bytearray_set_address_size(bytearray(8), 31) struct.pack_into("8s", name_buffer, 0, codecs.encode("{:8s}".format(name), encoding=cp1047_oe)) load_params = bytearray_set_address_size(bytearray(3*4), 31) struct.pack_into('IIBBBB', load_params, 0, bytearray_buffer_address(name_buffer), 0, 0, 0, 0x20, 0) svc_args = bytearray(5*8) struct.pack_into('QQQQQ', svc_args, 0, 9, 0, bytearray_buffer_address(load_params), 122, SYSTEM_CALL__SVC) zos_system_call(svc_args) #unsigned int r15; /* good:0 bad:returnCode */ #unsigned int r0; /* good:ep_including_amode bad:n/a */ #unsigned int r1; /* good:apf+length_in_doublewords bad:reasonCode */ codes = struct.unpack_from("4xI8x4xI", svc_args, 0) # ignore the high order 32 bits if codes[0] == 0: return struct.unpack_from("4xI", svc_args, 1*8)[0] else: raise OSError("LOAD return_code=%X, reason_code=%X" % codes)
def allocate_spool_dataset(data_set_name=None, client_token=None, subsystem=None): bytearray_set_address_size(client_token, 31) rc, results = dynalloc({ "DSNAME": data_set_name, "STATUS": "SHR", "UNAUTHORIZED_SUBSYSTER_REQUEST": subsystem, "BROWSE_TOKEN": (codecs.encode("BTKN", encoding=cp1047_oe), bytes( (3, 3)), bytearray_buffer_address(client_token).to_bytes( 4, sys.byteorder) if client_token else 0, 0, 0, 0, 0), "CLOSE": None, "DDNAME_RETURN": None }) if rc != 0: raise OSError("dynalloc returned %X" % rc) return results["DDNAME_RETURN"]
def bldl(self, name): a24 = self.a24 # BLDL bldl_list,dcb self.bldl_list = bytearray_set_address_size(bytearray(72), 31) bldl_list = self.bldl_list struct.pack_into('=HH8s', self.bldl_list, 0, 1, 68, codecs.encode("{:8s}".format(name), encoding=cp1047_oe) ) if self.verbose: print(["%08X" % v for v in struct.unpack_from('III', self.bldl_list, 0)]) struct.pack_into('QQQQQ', self.svc_args, 0, 0, bytearray_buffer_address(bldl_list), bytearray_buffer_address(a24) + dcb_offset, 18, SYSTEM_CALL__SVC) zos_system_call(self.svc_args) rc, reason = struct.unpack_from('7xB7xB', self.svc_args, 0) if rc > 0: raise OSError("BLDL failed for %s, rc=%X, reason=%X" % (self.name, rc, reason))
def open(self): # OPEN (dcb,(INPUT)),MODE=31 a24 = self.a24 open_args = bytearray_set_address_size(bytearray(8), 31) struct.pack_into('=B3xI', open_args, 0, 0x80, bytearray_buffer_address(a24) + dcb_offset) struct.pack_into('QQQQQ', self.svc_args, 0, 0, bytearray_buffer_address(open_args), 0, 19, SYSTEM_CALL__SVC) zos_system_call(self.svc_args) rc = struct.unpack_from('7xB', self.svc_args, 0)[0] if rc > 4: abend_code = struct.unpack_from('I', a24, 0)[0] if abend_code: raise OSError("OPEN abend %X" % abend_code) else: raise OSError("OPEN failed, rc=%X" % rc)
def volser_from_dsname(dsname, svc_args=None, encoding=None): if svc_args is None: svc_args = bytearray(5 * 8) if encoding is None: dsname = codecs.encode("{:44s}".format(dsname), encoding=cp1047_oe) locate = bytearray_set_address_size( bytearray(4 + 4 + 4 + 4 + 44 + 4 + 265), 31) struct.pack_into('=IIII' + '44s', locate, 0, 0x44000000, bytearray_buffer_address(locate) + 4 * 4, 0, bytearray_buffer_address(locate) + 4 * 4 + 44 + 4, dsname) struct.pack_into('QQQQQ', svc_args, 0, 0, 0, bytearray_buffer_address(locate), 26, SYSTEM_CALL__SVC) # LOCATE zos_system_call(svc_args) rc = struct.unpack_from('=4xI', svc_args, 0)[0] if rc != 0: raise OSError("LOCATE NAME returned rc=0x%X" % (rc, )) volser = struct.unpack_from('6s', locate, 4 * 4 + 44 + 4 + 2 + 4)[0] if encoding is None: volser = codecs.decode(volser_ebcdic, cp1047_oe) locate = None return volser
def dynallocInternal(verb, text_unit_mapping, flags1=0, flags2=0, verbose=False, message_level=0, message_function=print_message): keyword_definitions = text_keyword_definitions[verb] text_unit_array_size = process_text_units(text_unit_mapping, keyword_definitions, None, verbose=verbose) if verbose: print("test_unit_array_size = %r" % text_unit_array_size) text_unit_array = bytearray_set_address_size( bytearray(text_unit_array_size), 31) process_text_units(text_unit_mapping, keyword_definitions, text_unit_array, verbose=verbose) if verbose: show_text_units(text_unit_array) message_severity_level = 0 # informational, that is, include all the messages message_block_subpool = 4 message_options = 0x48 # return message to caller + specified subpool svc99rbx = bytearray_set_address_size(bytearray(36), 31) struct.pack_into( 'BBBBBBBBBBB', svc99rbx, 0, 0xE2, 0xF9, 0xF9, 0xD9, 0xC2, 0xE7, 1, #'S99RBX', version message_options, message_block_subpool, 8, message_severity_level) svc99rb = bytearray_set_address_size(bytearray(20), 31) struct.pack_into('BBHHHIII', svc99rb, 0, 20, verb_codes[verb], flags1, 0, 0, bytearray_buffer_address(text_unit_array), bytearray_buffer_address(svc99rbx), flags2) svc99plist = bytearray_set_address_size(bytearray(4), 31) struct.pack_into('I', svc99plist, 0, 0x80000000 | bytearray_buffer_address(svc99rb)) svc_args = bytearray(5 * 8) struct.pack_into('QQQQQ', svc_args, 0, 0, 0, bytearray_buffer_address(svc99plist), 99, SYSTEM_CALL__SVC) zos_system_call(svc_args) svc99_rc = struct.unpack_from('L', svc_args, 0)[0] if verbose: s99error_and_info = struct.unpack_from('HH', svc99rb, 4) print("s99rc=%X, error=%04X, info=%04X" % (svc99_rc, s99error_and_info[0], s99error_and_info[1])) show_text_units(text_unit_array) retrieve_dynalloc_messages(message_function, verb, keyword_definitions, svc99rbx, svc99rb, svc_args, verbose=verbose) output_mapping = process_text_units(text_unit_mapping, keyword_definitions, text_unit_array, tu_input=False, verbose=verbose) return (svc99_rc, output_mapping)
def retrieve_dynalloc_messages(message_function, verbName, keyword_definitions, svc99rbx, svc99rb, svc_args, verbose=False): svc99_rc = struct.unpack_from('L', svc_args, 0)[0] s99error = struct.unpack_from('H', svc99rb, 4)[0] s99info = struct.unpack_from('H', svc99rb, 6)[0] if svc99_rc != 0: message_function("%s failed, return code=%d, error=%04X, info=%04X" % (verbName, svc99_rc, s99error, s99info)) block_count = svc99rbx[11] if verbose: print("s99rbx message_count = %d" % block_count) if block_count == 0: return if block_count > MAX_EM_MESSAGES: block_count = MAX_EM_MESSAGES emMessages = bytearray_set_address_size(bytearray(256 * block_count), 31) emCall = bytearray_set_address_size(bytearray(28), 31) struct.pack_into('BBBxII4xI', emCall, 0, 0x20, 50, block_count, bytearray_buffer_address(svc99rb), svc99_rc, bytearray_buffer_address(emMessages)) if verbose: print(["%08X" % v for v in struct.unpack_from('IIIII', emCall, 0)]) emCallPlist = bytearray_set_address_size(bytearray(4), 31) struct.pack_into('I', emCallPlist, 0, 0x80000000 | bytearray_buffer_address(emCall)) save_area = bytearray_set_address_size(bytearray(18 * 4), 31) call_args = bytearray(5 * 8) struct.pack_into('QQQQQ', call_args, 0, get_IEFDB476(), 0, bytearray_buffer_address(emCallPlist), bytearray_buffer_address(save_area), SYSTEM_CALL__CALL31) zos_system_call(call_args) IEFDB476_rc = struct.unpack_from('Q', call_args, 0)[0] if verbose: print("IEFDB476_rc=%X" % IEFDB476_rc) if verbose: print( ["%X" % v for v in struct.unpack_from('xxBBIIHHI', svc99rbx, 16)]) print(["%X" % v for v in struct.unpack_from('BBBxII4xI', emCall, 0)]) print("block_count=%X" % block_count) for i in range(block_count): message_length = struct.unpack_from('H', emMessages, 256 * i)[0] if verbose: print('message_length=%d' % message_length) message_text = emMessages[256 * i + 4:256 * i + 4 + message_length] message = str.rstrip(codecs.decode(message_text, cp1047_oe)) message_function(message) if s99error == 0x035C: # Invalid PARM specified in text unit, with corresponding message IKJ56231I info = keyword_definitions[s99info] if info: message_function("text unit %04X is %s %s" % (s99info, info[0][0], info[0][2]))
class extended_status: verbose = False ssreq_fn = MEM4(MEM4(MEM4(0, 0x10), 0x128), 0x14) ssob_and_stat_len = 0x23C # version 10 ssob_and_stat = bytearray_set_address_size(bytearray(ssob_and_stat_len), 31) arglist = bytearray_set_address_size(bytearray(4), 31) struct.pack_into('=I', arglist, 0, bytearray_buffer_address(ssob_and_stat)) struct.pack_into( '=4sHHI4xI', ssob_and_stat, 0, codecs.encode("{:4s}".format("SSOB"), encoding=cp1047_oe), # E2E2D6C2 0x1C, 80, 0, bytearray_buffer_address(ssob_and_stat) + 0x20) # 0x1C is the SSOB length; 80 is extended status struct.pack_into( 'H4sBB5x', ssob_and_stat, 0x20, 0x21C, # version 10 length codecs.encode("{:4s}".format("STAT"), encoding=cp1047_oe), # E2E3C1E3 10, 0) # version 10, modifier 0 struct.pack_into( 'B', ssob_and_stat, 0xDA, # STATOPT1 0x04) # Returned areas may be obtained in 64-bit storage save_area = bytearray_set_address_size(bytearray(18 * 4), 31) ssreq = bytearray(5 * 8) def call(self, request_type, criteria={}, requested_fields=None): self.requested_fields = requested_fields ssob_and_stat = self.ssob_and_stat arglist = self.arglist save_area = self.save_area ssreq = self.ssreq request_types = ('job_terse', 'job_verbose', 'close', 'sysout_terse', 'sysout_verbose', 'data_set_list') struct.pack_into('B', ssob_and_stat, 0x2C, request_types.index(request_type) + 1) for name, value in criteria.items(): if not value: continue struct_fmt, position_list, bit_position, bit = criteria_fields[ name] if isinstance(value, str): value = codecs.encode( ("{:%ds}" % int(struct_fmt[:-1])).format(value), encoding=cp1047_oe) if isinstance(position_list, tuple): for position in position_list: struct.pack_into(struct_fmt, ssob_and_stat, position, value) else: position = position_list struct.pack_into(struct_fmt, ssob_and_stat, position, value) ssob_and_stat[bit_position] |= bit struct.pack_into('QQQQQ', ssreq, 0, ssreq_fn, 0, bytearray_buffer_address(arglist), bytearray_buffer_address(save_area), SYSTEM_CALL__CALL31) zos_system_call(ssreq) self.ssi_return_code = struct.unpack_from('=4xI', self.ssreq, 0)[0] if self.ssi_return_code != 0: error_index = self.ssi_return_code / 4 - 1 error_messages = ( "The subsystem does not support this function.", "The subsystem exists, but is not active.", "The subsystem is not defined to MVS.", "Invalid SSOB, SSIB or function code", "The SSOB or SSIB have invalid lengths or formats", "The SSI has not been initialized.") raise Exception(error_messages[errior_index]) self.subsystem_return_code = struct.unpack_from( '=I', ssob_and_stat, 0x0C)[0] # SSOBRETN self.version, self.reason, self.reason2 = struct.unpack_from( '=BxBB', self.ssob_and_stat, 0x28) # STATVER, STATREAS, STATREA2 if self.ssi_return_code == 4: raise Exception("Invalid search arguments") elif self.ssi_return_code == 8: raise Exception("Logic error, reason=0x%X" % self.reason) elif self.ssi_return_code == 12: raise Exception("Unsupported call type") #print(dump_region(bytearray_buffer_address(ssob_and_stat), len(self.ssob_and_stat))) return None def job_elements(self): have_64bit_results = struct.unpack_from('B', self.ssob_and_stat, 0x108)[0] & 0x40 for self.jq64 in (True, False) if have_64bit_results else (False, ): self.jqe_address = struct.unpack_from( 'Q' if self.jq64 else 'I', self.ssob_and_stat, 0x118 if self.jq64 else 0x0F4)[0] if self.verbose: print("jq64=%r, jqe=%X" % (self.jq64, self.jqe_address)) while self.jqe_address: self.subsystem_name = codecs.decode((ctypes.c_char*4)\ .from_address(self.jqe_address + 0x10).value, cp1047_oe) job = {"subsystem": self.subsystem_name} job = self.parse_element_information(self.jqe_address, 'job_terse', job) self.job_verbose_address = (ctypes.c_ulong if self.jq64 else ctypes.c_uint)\ .from_address(self.jqe_address + (0x30 if self.jq64 else 0x14)).value if self.job_verbose_address: if self.verbose: print("job_verbose=%X" % (self.job_verbose_address, )) job = self.parse_element_information( self.job_verbose_address, 'job_verbose', job) yield job self.jqe_address = (ctypes.c_ulong if self.jq64 else ctypes.c_uint)\ .from_address(self.jqe_address + (0x20 if self.jq64 else 0x08)).value if self.verbose: print("jqe=%X" % (self.jqe_address, )) def job_dependency_elements(self): if ctypes.c_short.from_address(self.jqe_address + 0x4).value >= 0x48: self.dependency_address = ctypes.c_ulong.from_address( self.jqe_address + 0x40).value while self.dependency_address: yield self.parse_element_information(self.dependency_address, 'job_dependency') self.dependency_address = ctypes.c_ulong.from_address( self.dependency_address + 0x8).value def sysout_terse_elements(self): self.sysout_terse_address = (ctypes.c_ulong if self.jq64 else ctypes.c_uint)\ .from_address(self.jqe_address + (0x28 if self.jq64 else 0x0C)).value while self.sysout_terse_address: yield self.parse_element_information(self.sysout_terse_address, 'sysout_terse') self.sysout_terse_address = (ctypes.c_ulong if self.jq64 else ctypes.c_uint)\ .from_address(self.sysout_terse_address + (0x18 if self.jq64 else 0x08)).value def sysout_verbose_elements(self): self.sysout_verbose_address = (ctypes.c_ulong if self.jq64 else ctypes.c_uint)\ .from_address(self.sysout_terse_address + (0x28 if self.jq64 else 0x10)).value while self.sysout_verbose_address: yield self.parse_element_information(self.sysout_verbose_address, 'sysout_verbose') self.sysout_verbose_address = (ctypes.c_ulong if self.jq64 else ctypes.c_uint)\ .from_address(self.sysout_verbose_address + (0x30 if self.jq64 else 0x14)).value def parse_element_information(self, header_address, header_type, result=None): if not result: result = {} offset = ctypes.c_ushort.from_address(header_address + 0x4).value total_length = ctypes.c_ushort.from_address(header_address + offset + 0x0).value address = header_address + offset offset = 4 while offset < total_length: section_length = ctypes.c_ushort.from_address(address + offset + 0x0).value result = self.parse_information(address + offset, total_length - offset, result) offset += section_length return result def parse_information(self, address, remaining_length, result=None): if not result: result = {} type_and_modifier = ctypes.c_ushort.from_address(address + 0x2).value data_format = structure_info.get(type_and_modifier, ()) if data_format: address += 4 for name, ctype, offset, convert, size in data_format: if name and (not self.requested_fields or name in self.requested_fields): if self.verbose: print("%X %s %s" % (offset, name, dump_region(address + offset, size, show_header=False, show_address=False)), flush=True) if ctype: value = convert( ctype.from_address(address + offset).value) else: value = bytearray(size) ctypes.memmove(bytearray_buffer_address(value), address + offset, size) if value: result[name] = value return result