mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
libvmcp: Add common vmcp code to the lib
This patch prevents code duplication in vmcp related programs. Some applications such as vmur, vmcp, and lsqeth use z/VM CP commands to query information. Each program uses its own defines and code. Supply a library and common header file to use common code. Signed-off-by: Thomas Richter <tmricht@linux.vnet.ibm.com> Reviewed-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com> Reviewed-by: Jan Höppner <hoeppner@linux.vnet.ibm.com> Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
committed by
Jan Höppner
parent
37c3752b31
commit
eaa2ef6ba4
1
.gitignore
vendored
1
.gitignore
vendored
@@ -46,6 +46,7 @@ libutil/util_prg_example
|
||||
libutil/util_rec_example
|
||||
libutil/util_scandir_example
|
||||
libzds/libzds.a
|
||||
libvmcp/vmcp_example
|
||||
mon_tools/mon_fsstatd
|
||||
mon_tools/mon_procd
|
||||
osasnmpd/osasnmpd
|
||||
|
||||
2
Makefile
2
Makefile
@@ -3,7 +3,7 @@ ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/ar
|
||||
# Include common definitions
|
||||
include common.mak
|
||||
|
||||
LIB_DIRS = libvtoc libu2s libutil libzds libdasd libvmdump libccw
|
||||
LIB_DIRS = libvtoc libu2s libutil libzds libdasd libvmdump libccw libvmcp
|
||||
TOOL_DIRS = zipl zdump fdasd dasdfmt dasdview tunedasd \
|
||||
tape390 osasnmpd qetharp ip_watcher qethconf scripts zconf \
|
||||
vmconvert vmcp man mon_tools dasdinfo vmur cpuplugd ipl_tools \
|
||||
|
||||
@@ -338,6 +338,10 @@ $(rootdir)/libvmdump/libvmdump.a: $(rootdir)/libvmdump
|
||||
$(MAKE) -C $(rootdir)/libvmdump/ libvmdump.a
|
||||
.PHONY: $(rootdir)/libvmdump
|
||||
|
||||
$(rootdir)/libvmcp/libvmcp.a: $(rootdir)/libvmcp
|
||||
$(MAKE) -C $(rootdir)/libvmcp/ libvmcp.a
|
||||
.PHONY: $(rootdir)/libvmcp
|
||||
|
||||
$(rootdir)/zipl/boot/data.o:
|
||||
$(MAKE) -C $(rootdir)/zipl/boot/ data.o
|
||||
|
||||
|
||||
52
include/lib/vmcp.h
Normal file
52
include/lib/vmcp.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* vmcp - z/VM CP command library
|
||||
*
|
||||
* Copyright IBM Corp. 2005, 2018
|
||||
*
|
||||
* s390-tools is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
*/
|
||||
|
||||
#ifndef LIB_VMCP_H
|
||||
#define LIB_VMCP_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define VMCP_DEVICE_NODE "/dev/vmcp" /* VMCP device name */
|
||||
#define VMCP_DEFAULT_BUFSZ 0x4000 /* VMCP default buffer size */
|
||||
|
||||
/*
|
||||
* Error codes returned by vmcp() function. This enables the caller
|
||||
* to emit a detailed error message on the type of failure.
|
||||
*/
|
||||
#define VMCP_SUCCESS 0 /* VMCP operation completed successfully */
|
||||
#define VMCP_ERR_OPEN (-1) /* Error Open of VMCP device */
|
||||
#define VMCP_ERR_SETBUF (-2) /* Error VMCP_SETBUF ioctl */
|
||||
#define VMCP_ERR_READ (-3) /* Error VMCP read system call */
|
||||
#define VMCP_ERR_GETCODE (-4) /* Error VMCP_GETCODE ioctl */
|
||||
#define VMCP_ERR_GETSIZE (-5) /* Error VMCP_GETSIZE ioctl */
|
||||
#define VMCP_ERR_TOOSMALL (-6) /* Error VMCP buffer too small for
|
||||
* response
|
||||
*/
|
||||
#define VMCP_ERR_WRITE (-7) /* Error VMCP write system call */
|
||||
|
||||
struct vmcp_parm {
|
||||
const char *cpcmd;
|
||||
unsigned int buffer_size;
|
||||
bool do_upper;
|
||||
int cprc;
|
||||
char *response;
|
||||
unsigned int response_size;
|
||||
};
|
||||
|
||||
int vmcp(struct vmcp_parm *cp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
18
libvmcp/Makefile
Normal file
18
libvmcp/Makefile
Normal file
@@ -0,0 +1,18 @@
|
||||
include ../common.mak
|
||||
|
||||
lib = libvmcp.a
|
||||
|
||||
examples = vmcp_example
|
||||
|
||||
all: $(lib) $(examples)
|
||||
|
||||
objects = vmcp.o
|
||||
|
||||
$(lib): $(objects)
|
||||
|
||||
install: all
|
||||
|
||||
vmcp_example: vmcp_example.o $(lib) $(rootdir)/libutil/libutil.a
|
||||
|
||||
clean:
|
||||
rm -f *.o $(lib) $(examples)
|
||||
134
libvmcp/vmcp.c
Normal file
134
libvmcp/vmcp.c
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* vmcp - z/VM CP function library
|
||||
*
|
||||
* Copyright IBM Corp. 2018
|
||||
*
|
||||
* s390-tools is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include "lib/util_libc.h"
|
||||
#include "lib/vmcp.h"
|
||||
|
||||
#define VMCP_DEVICE_NODE "/dev/vmcp"
|
||||
#define VMCP_GETSIZE _IOR(0x10, 3, int)
|
||||
#define VMCP_SETBUF _IOW(0x10, 2, int)
|
||||
#define VMCP_GETCODE _IOR(0x10, 1, int)
|
||||
|
||||
/*
|
||||
* Read at most COUNT bytes from FD into memory at location BUF.
|
||||
* Return number of bytes read on success, -1 on error.
|
||||
*/
|
||||
static ssize_t read_buffer(int fd, char *buf, ssize_t count)
|
||||
{
|
||||
ssize_t ret, done;
|
||||
|
||||
for (done = 0; done < (ssize_t)count; done += ret) {
|
||||
ret = read(fd, &buf[done], count - done);
|
||||
if (ret == -1 && errno == EINTR)
|
||||
continue;
|
||||
if (ret == -1)
|
||||
return -1;
|
||||
if (ret == 0)
|
||||
break;
|
||||
}
|
||||
return done;
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit a command to z/VM CP and return the response, the size in bytes
|
||||
* of the response and CP command response code.
|
||||
*
|
||||
* The member response contains the response from CP. It is a pointer
|
||||
* to a malloc'ed buffer which must be freed by the caller when the return
|
||||
* code is zero or VMCP_ERR_TOOSMALL.
|
||||
*
|
||||
* @param[in,out] cmd Pointer to struct vmcp_parm.
|
||||
* @param[in] cpcmd Pointer to CP command string.
|
||||
* @param[in] do_upper If true convert cpcmd string to upper case.
|
||||
* @param[out] cprc Return code of the CP command.
|
||||
* @param[out] response Return buffer, has been allocated via malloc()
|
||||
* must be freed by caller, see below.
|
||||
* @param[out] response_size Size of the response in bytes, can be larger
|
||||
* than buffer_size.
|
||||
*
|
||||
* @returns Zero on success or a negative error number on failure.
|
||||
* @retval VMCP_SUCCESS Success valid members: cprc, response,
|
||||
* response_size
|
||||
* @retval VMCP_ERR_OPEN Error opening VMCP device, valid members: none
|
||||
* @retval VMCP_ERR_SETBUF Error setting buffer, valid members: none
|
||||
* @retval VMCP_ERR_GETCODE Error getting cp exit code, valid members: none
|
||||
* @retval VMCP_ERR_WRITE Error write CP command, valid members: none
|
||||
* @retval VMCP_ERR_GETSIZE Error reading response size,
|
||||
* valid members: cprc
|
||||
* @retval VMCP_ERR_READ Error reading resp
|
||||
* @retval VMCP_ERR_TOOSMALL Error response buffer too small, response
|
||||
* truncated, valid members: cprc, response,
|
||||
* response_size
|
||||
*/
|
||||
int vmcp(struct vmcp_parm *cmd)
|
||||
{
|
||||
int rc = VMCP_SUCCESS, fd, len;
|
||||
char *cpcmd;
|
||||
|
||||
cmd->response = NULL;
|
||||
cmd->response_size = 0;
|
||||
cmd->cprc = 0;
|
||||
|
||||
fd = open(VMCP_DEVICE_NODE, O_RDWR);
|
||||
if (fd == -1)
|
||||
return VMCP_ERR_OPEN;
|
||||
|
||||
cpcmd = util_strdup(cmd->cpcmd); /* Exits on failure */
|
||||
if (cmd->do_upper)
|
||||
util_str_toupper(cpcmd);
|
||||
|
||||
if (ioctl(fd, VMCP_SETBUF, &cmd->buffer_size) == -1) {
|
||||
rc = VMCP_ERR_SETBUF;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (write(fd, cpcmd, strlen(cpcmd)) == -1) {
|
||||
rc = VMCP_ERR_WRITE;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (ioctl(fd, VMCP_GETCODE, &cmd->cprc) == -1) {
|
||||
rc = VMCP_ERR_GETCODE;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (ioctl(fd, VMCP_GETSIZE, &cmd->response_size) == -1) {
|
||||
rc = VMCP_ERR_GETSIZE;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (cmd->response_size <= cmd->buffer_size) {
|
||||
len = cmd->response_size;
|
||||
} else {
|
||||
len = cmd->buffer_size;
|
||||
rc = VMCP_ERR_TOOSMALL;
|
||||
}
|
||||
|
||||
/* Exits on failure */
|
||||
cmd->response = (char *)util_zalloc(len + 1);
|
||||
|
||||
if (read_buffer(fd, cmd->response, len) == -1) {
|
||||
rc = VMCP_ERR_READ;
|
||||
free(cmd->response);
|
||||
cmd->response = NULL;
|
||||
}
|
||||
|
||||
fail:
|
||||
close(fd);
|
||||
free(cpcmd);
|
||||
return rc;
|
||||
}
|
||||
65
libvmcp/vmcp_example.c
Normal file
65
libvmcp/vmcp_example.c
Normal file
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* vmcp_example - Example program for vmcp.c
|
||||
*
|
||||
* Copyright 2018 IBM Corp.
|
||||
*
|
||||
* s390-tools is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
*/
|
||||
|
||||
//! [code]
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <err.h>
|
||||
|
||||
#include "lib/vmcp.h"
|
||||
|
||||
/*
|
||||
* Demonstrate vmcp() function usage
|
||||
*/
|
||||
int main(void)
|
||||
{
|
||||
struct vmcp_parm cp;
|
||||
int rc;
|
||||
|
||||
cp.cpcmd = "q osa";
|
||||
cp.buffer_size = VMCP_DEFAULT_BUFSZ;
|
||||
cp.do_upper = true;
|
||||
|
||||
rc = vmcp(&cp);
|
||||
|
||||
switch (rc) {
|
||||
case VMCP_SUCCESS:
|
||||
printf("%s\n", cp.response);
|
||||
free(cp.response);
|
||||
break;
|
||||
case VMCP_ERR_OPEN:
|
||||
errx(EXIT_FAILURE, "Could not open device %s", VMCP_DEVICE_NODE);
|
||||
break;
|
||||
case VMCP_ERR_SETBUF:
|
||||
errx(EXIT_FAILURE, "Could not set buffer size");
|
||||
break;
|
||||
case VMCP_ERR_GETCODE:
|
||||
errx(EXIT_FAILURE, "Could not query return code");
|
||||
break;
|
||||
case VMCP_ERR_GETSIZE:
|
||||
errx(EXIT_FAILURE, "Could not query response size");
|
||||
break;
|
||||
case VMCP_ERR_WRITE:
|
||||
errx(EXIT_FAILURE, "Could not issue CP command");
|
||||
break;
|
||||
case VMCP_ERR_READ:
|
||||
errx(EXIT_FAILURE, "Could not read CP response");
|
||||
break;
|
||||
case VMCP_ERR_TOOSMALL:
|
||||
free(cp.response);
|
||||
printf("Response truncated (requires %u bytes)\n",
|
||||
cp.response_size);
|
||||
errx(EXIT_FAILURE, "Response buffer (%u bytes) too small",
|
||||
cp.buffer_size);
|
||||
break;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
//! [code]
|
||||
Reference in New Issue
Block a user