From f0da66ef81e16a84470fb563c8c5c7094043e61e Mon Sep 17 00:00:00 2001 From: Deon George Date: Tue, 16 Jul 2013 09:58:53 +1000 Subject: [PATCH] Added Session Info reporting --- Makefile.linux64 | 2 +- tsmpipe.c | 327 ++++++++++++++++++++++++++++++++++------------- 2 files changed, 237 insertions(+), 92 deletions(-) diff --git a/Makefile.linux64 b/Makefile.linux64 index 359b581..ee6e1bb 100644 --- a/Makefile.linux64 +++ b/Makefile.linux64 @@ -1,7 +1,7 @@ TSMAPIDIR=/opt/tivoli/tsm/client/api/bin64/sample TSMLIB=-lApiTSM64 CC=gcc -CFLAGS=-g -W -Wall -O -I$(TSMAPIDIR) +CFLAGS=-g -W -Wall -Wextra -O -I$(TSMAPIDIR) LDFLAGS= FILES=tsmpipe.c diff --git a/tsmpipe.c b/tsmpipe.c index dadc984..1f2088f 100644 --- a/tsmpipe.c +++ b/tsmpipe.c @@ -18,10 +18,9 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ -static const char rcsid[] = /*Add RCS version string to binary */ - "$Id: tsmpipe.c,v 1.5-dg 2010/02/15 07:41:26 nikke Exp $"; + Modifications Copyright(c) 2012-2013 by Deon George +*/ /* Enable Large File Support stuff */ #define _FILE_OFFSET_BITS 64 @@ -53,14 +52,14 @@ static const char rcsid[] = /*Add RCS version string to binary */ * 64kB + 4 bytes limit or if your TCPBUFLEN is lower, the * n*TCPBUFFLEN - 4 bytes that gets you closest to 64kB. * - * For a default tuned TSM client on Linux, BUFLEN should thus be 32*1024*2-4. + * For a default tuned TSM client on Linux, BUFLEN should thus be 64*1024-4. */ -/* We (HPC2N) have 512kB tcpbuff */ #define BUFLEN (64*1024-4) -static dsmDate xStringToDate (char *s); +static dsmDate xStringToDate (char *s); +/* Convert a string number into a number */ off_t atooff(const char *s) { off_t o; @@ -77,53 +76,40 @@ off_t atooff(const char *s) return o; } - -ssize_t read_full(int fd, void *buf, size_t count) { - ssize_t done=0; - - while(count) { - ssize_t len; - - len = read(fd, buf+done, count); - if(len == 0) { - break; - } - else if(len < 0) { - if(errno == EINTR) { - continue; - } - else { - if(done == 0) { - done = -1; - } - break; - } - } - count -= len; - done += len; - } - - return(done); -} - - -ssize_t write_full(int fd, const void *buf, size_t count) +/* Read/Write a buffer full of data from file descripter */ +ssize_t rw_full(int fd, void *buf, size_t count) { ssize_t done=0; - while(count) { + while (count) { ssize_t len; - len = write(fd, buf+done, count); - if(len < 0) { - if(errno == EINTR) { + if (fd == STDIN_FILENO) { + len = read(fd, buf+done, count); + + } else if (fd == STDOUT_FILENO) { + len = write(fd, buf+done, count); + + } else { + fprintf(stderr, "tsmpipe: rw_full: Unknown FD\n"); + exit(1); + } + + if (len == 0) { + break; + + } else if (len < 0) { + if (errno == EINTR) { continue; - } - else { - done = -1; + + } else { + if (done == 0) + done = -1; + break; } } + count -= len; done += len; } @@ -131,52 +117,48 @@ ssize_t write_full(int fd, const void *buf, size_t count) return(done); } - +/* Check the TSM API Version */ int tsm_checkapi(void) { - dsmApiVersionEx apiLibVer; - dsUint32_t apiVersion; - dsUint32_t applVersion = (10000 * DSM_API_VERSION) + - (1000 * DSM_API_RELEASE) + - (100 * DSM_API_LEVEL) + DSM_API_SUBLEVEL; + dsmApiVersionEx apiLibVer; + dsUint32_t apiVersion; + dsUint32_t applVersion = (10000 * DSM_API_VERSION) + (1000 * DSM_API_RELEASE) + (100 * DSM_API_LEVEL) + DSM_API_SUBLEVEL; memset(&apiLibVer, 0, sizeof(apiLibVer)); apiLibVer.stVersion = apiVersionExVer; dsmQueryApiVersionEx(&apiLibVer); apiVersion = (10000 * apiLibVer.version) + (1000 * apiLibVer.release) + - (100 * apiLibVer.level) + apiLibVer.subLevel; + (100 * apiLibVer.level) + apiLibVer.subLevel; - if (apiVersion < applVersion) - { - printf("The Tivoli Storage Manager API library Version = %d.%d.%d.%d " - "is at a lower version\n", - apiLibVer.version, - apiLibVer.release, - apiLibVer.level, - apiLibVer.subLevel); + if (apiVersion < applVersion) { + printf("The Tivoli Storage Manager API library Version = %d.%d.%d.%d is at a lower version\n", + apiLibVer.version, + apiLibVer.release, + apiLibVer.level, + apiLibVer.subLevel); printf("than the application version = %d.%d.%d.%d.\n", - DSM_API_VERSION, - DSM_API_RELEASE, - DSM_API_LEVEL, - DSM_API_SUBLEVEL); + DSM_API_VERSION, + DSM_API_RELEASE, + DSM_API_LEVEL, + DSM_API_SUBLEVEL); printf("Please upgrade the API accordingly.\n"); + return 0; } return 1; } - +/* Print out TSM Error Code */ void tsm_printerr(dsUint32_t sesshandle, dsInt16_t rc, char *str) { - char rcStr[DSM_MAX_RC_MSG_LENGTH]; + char rcStr[DSM_MAX_RC_MSG_LENGTH]; - if(rc == DSM_RC_WILL_ABORT) { + if (rc == DSM_RC_WILL_ABORT) { dsUint16_t reason; rc = dsmEndTxn(sesshandle, DSM_VOTE_COMMIT, &reason); - if(rc == DSM_RC_CHECK_REASON_CODE) { + if (rc == DSM_RC_CHECK_REASON_CODE) rc = reason; - } } dsmRCMsg(sesshandle, rc, rcStr); @@ -184,13 +166,17 @@ void tsm_printerr(dsUint32_t sesshandle, dsInt16_t rc, char *str) { " rc=%s\n", str, rcStr); } - +/* @TODO: Need to force compressalways if compression is on */ dsUint32_t tsm_initsess(char *options) { - dsmApiVersionEx applApi; - dsUint32_t sesshandle = 0; - dsmInitExIn_t initIn; - dsmInitExOut_t initOut; - dsInt16_t rc; + dsmApiVersionEx applApi; + dsUint32_t sesshandle = 0; + dsmInitExIn_t initIn; + dsmInitExOut_t initOut; + + dsInt16_t rc; + optStruct dsmOpt1; + ApiSessInfo dsmSessInfo; + char t[50]; memset(&applApi, 0, sizeof(applApi)); applApi.version = DSM_API_VERSION; @@ -213,23 +199,135 @@ dsUint32_t tsm_initsess(char *options) { memset(&initOut, 0, sizeof(initOut)); rc = dsmInitEx(&sesshandle, &initIn, &initOut); + /* If the TSM password has expired, change it. */ if(rc == DSM_RC_REJECT_VERIFIER_EXPIRED) { rc = dsmChangePW(sesshandle, NULL, NULL); if(rc != DSM_RC_OK) { tsm_printerr(sesshandle, rc, "dsmChangePW failed"); return 0; } - } - else if(rc != DSM_RC_OK) { + + } else if(rc != DSM_RC_OK) { tsm_printerr(sesshandle, rc, "dsmInitEx failed"); dsmTerminate(sesshandle); return 0; } + memset(&dsmOpt1, 0, sizeof(dsmOpt1)); + rc = dsmQuerySessOptions(sesshandle, &dsmOpt1); + + if (rc) + printf("dsmQuerySessOptions error on issueing Query Session Options. Rc = %d\n",rc); + else { + printf("++dsmQuerySessOptions:\n"); + printf("DSMI_DIR >%s<\n", dsmOpt1.dsmiDir); + printf("DSMI_CONFIG >%s<\n", dsmOpt1.dsmiConfig); + printf("serverName >%s<\n", dsmOpt1.serverName); + printf("commMethod %d\n", dsmOpt1.commMethod); + printf("serverAddress >%s<\n", dsmOpt1.serverAddress); + printf("nodeName >%s<\n", dsmOpt1.nodeName); + printf("compress %d\n", dsmOpt1.compression); + printf("compressalways %d\n", dsmOpt1.compressalways); + printf("passwordAccess %d\n", dsmOpt1.passwordAccess); + } + + memset(&dsmSessInfo, 0x00, sizeof(ApiSessInfo)); + dsmSessInfo.stVersion = ApiSessInfoVersion; /* Init struct version */ + rc = dsmQuerySessInfo(sesshandle, &dsmSessInfo); + if (rc) + printf("dsmQuerySessOptions error on issueing Query Session Options. Rc = %d\n",rc); + else { + printf("\ndsmQuerySessInfo Values:\n"); + printf(" Server Information:\n"); + printf(" Server name: %s\n",dsmSessInfo.adsmServerName); + + printf(" Server Host: %s\n",dsmSessInfo.serverHost); + printf(" Server port: %u\n",dsmSessInfo.serverPort); + printf(" Server date: %i/%i/%i %i:%i:%i\n", + dsmSessInfo.serverDate.year, + (dsInt16_t)dsmSessInfo.serverDate.month, + (dsInt16_t)dsmSessInfo.serverDate.day, + (dsInt16_t)dsmSessInfo.serverDate.hour, + (dsInt16_t)dsmSessInfo.serverDate.minute, + (dsInt16_t)dsmSessInfo.serverDate.second); + printf(" Server type: %s\n",dsmSessInfo.serverType); + printf(" Server version: %i.%i.%i.%i\n", + dsmSessInfo.serverVer, + dsmSessInfo.serverRel, + dsmSessInfo.serverLev, + dsmSessInfo.serverSubLev); + printf(" Server Archive Retention Protection : %s (%i)\n",dsmSessInfo.archiveRetentionProtection ? "YES" : "NO",dsmSessInfo.archiveRetentionProtection); + printf(" Client Information:\n"); + printf(" Client node type: %s\n",dsmSessInfo.nodeType); + printf(" Client filespace delimiter: %c\n",dsmSessInfo.fsdelim); + printf(" Client hl & ll delimiter: %c\n",dsmSessInfo.hldelim); + + switch (dsmSessInfo.compression) + { + case COMPRESS_YES : + strcpy(t,"ON"); + break; + case COMPRESS_NO : + strcpy(t,"OFF"); + break; + case COMPRESS_CD : + strcpy(t,"Client determined"); + break; + default : + strcpy(t,"Unknown compress state."); + } + printf(" Client compression: %s (%i)\n",t,dsmSessInfo.compression); + + switch (dsmSessInfo.archDel) + { + case ARCHDEL_YES : + strcpy(t,"Client can delete archived objects"); + break; + case ARCHDEL_NO : + strcpy(t,"Client CANNOT delete archived objects"); + break; + default : + strcpy(t,"Unknown archive delete state"); + } + printf(" Client archive delete: %s\n",t); + + switch (dsmSessInfo.backDel) + { + case BACKDEL_YES : + strcpy(t,"Client can delete backup objects"); + break; + case ARCHDEL_NO : + strcpy(t,"Client CANNOT delete backup objects"); + break; + default : + strcpy(t,"Unknown backup delete state"); + } + printf(" Client backup delete: %s\n",t); + printf(" Maximum objects in multiple object transactions: %u\n", dsmSessInfo.maxObjPerTxn); + printf(" Lan free Enabled: %s(%i)\n",dsmSessInfo.lanFreeEnabled ? "YES" : "NO",dsmSessInfo.lanFreeEnabled); + printf(" Deduplication : %s(%i)\n",dsmSessInfo.dedupType == dedupClientOrServer ? "Client Or Server" : "Server Only",dsmSessInfo.dedupType); + printf(" General session info:\n"); + printf(" Node: %s\n",dsmSessInfo.id); + printf(" Owner: %s\n",dsmSessInfo.owner); + printf(" API Config file: %s\n",dsmSessInfo.confFile); + printf(" Policy Information:\n"); + printf(" Domain name: %s\n",dsmSessInfo.domainName); + printf(" Policyset name: %s\n",dsmSessInfo.policySetName); + printf(" Policy activation date: %i/%i/%i %i:%i:%i\n", + dsmSessInfo.polActDate.year, + (dsInt16_t)dsmSessInfo.polActDate.month, + (dsInt16_t)dsmSessInfo.polActDate.day, + (dsInt16_t)dsmSessInfo.polActDate.hour, + (dsInt16_t)dsmSessInfo.polActDate.minute, + (dsInt16_t)dsmSessInfo.polActDate.second); + printf(" Default management class: %s\n",dsmSessInfo.dfltMCName); + printf(" Backup retention grace period: %u days\n", dsmSessInfo.gpBackRetn); + printf(" Archive retention grace period: %u days\n", dsmSessInfo.gpArchRetn); + } + return sesshandle; } - int tsm_regfs(dsUint32_t sesshandle, char *fsname) { regFSData regFS; dsInt16_t rc; @@ -290,6 +388,12 @@ int tsm_sendfile(dsUint32_t sesshandle, char *fsname, char *filename, DataBlk dataBlk; ssize_t nbytes; + dsmEndSendObjExIn_t dsmEndSendObjExIn; + dsmEndSendObjExOut_t dsmEndSendObjExOut; + + memset(&dsmEndSendObjExIn, 0x00, sizeof(dsmEndSendObjExIn_t)); + memset(&dsmEndSendObjExOut,0x00, sizeof(dsmEndSendObjExOut_t)); + buffer = malloc(BUFLEN); if(!buffer) { perror("tsmpipe: malloc"); @@ -355,7 +459,7 @@ int tsm_sendfile(dsUint32_t sesshandle, char *fsname, char *filename, dataBlk.stVersion = DataBlkVersion; while(1) { - nbytes = read_full(STDIN_FILENO, buffer, BUFLEN); + nbytes = rw_full(STDIN_FILENO, buffer, BUFLEN); if(nbytes < 0) { perror("tsmpipe: read"); @@ -376,11 +480,22 @@ int tsm_sendfile(dsUint32_t sesshandle, char *fsname, char *filename, } } + /* rc = dsmEndSendObj(sesshandle); if(rc != DSM_RC_OK && rc != DSM_RC_COMPRESS_GREW) { tsm_printerr(sesshandle, rc, "dsmEndSendObj failed"); return(0); } + */ + dsmEndSendObjExIn.stVersion = dsmEndSendObjExInVersion; + dsmEndSendObjExIn.dsmHandle = sesshandle; + dsmEndSendObjExOut.stVersion = dsmEndSendObjExOutVersion; + + if ((rc = dsmEndSendObjEx(&dsmEndSendObjExIn, &dsmEndSendObjExOut)) != DSM_RC_OK) + { + tsm_printerr(sesshandle, rc, "dsmEndSendObj failed"); + return(0); + } rc = dsmEndTxn(sesshandle, DSM_VOTE_COMMIT, &reason); if(rc == DSM_RC_CHECK_REASON_CODE || @@ -394,6 +509,28 @@ int tsm_sendfile(dsUint32_t sesshandle, char *fsname, char *filename, return(0); } + /* + dI64toCh(&endSendObjExOut.totalBytesSent,t,10); + format_number(t,t2); + printf("Total bytes sent: %s\n", t2); + printf("Compression: %s\n", endSendObjExOut.objCompressed == bTrue ? "YES" : "NO"); + + dI64toCh(&endSendObjExOut.totalCompressSize,t,10); + format_number(t,t2); + printf("Compressed size: %s\n", t2); + + dI64toCh(&endSendObjExOut.totalLFBytesSent,t,10); + format_number(t,t2); + printf("LAN-free bytes sent: %s\n", t2); + + printf("Encryption: %s\n", endSendObjExOut.encryptionType & DSM_ENCRYPT_CLIENTENCRKEY ? "CLIENTENCRKEY" : endSendObjExOut.encryptionType & DSM_ENCRYPT_USER ? "USER" : "NO"); + printf("Encryption Strength: %s\n", endSendObjExOut.encryptionType & DSM_ENCRYPT_AES_128BIT ? "AES_128BIT" : endSendObjExOut.encryptionType & DSM_ENCRYPT_DES_56BIT ? "DES_56BIT" : "NONE"); + printf("Object Deduplicated: %s\n", endSendObjExOut.objDeduplicated ? "YES" : "NO"); + dI64toCh(&endSendObjExOut.totalDedupSize,t,10); + format_number(t,t2); + printf("Deduplicated size: %s\n\n", t2); + */ + return 1; } @@ -639,6 +776,7 @@ int tsm_deletefile(dsUint32_t sesshandle, char *fsname, char *filename, } +/* @TODO Need to assume latest active if PIT not specified */ int tsm_restorefile(dsUint32_t sesshandle, char *fsname, char *filename, char *description, dsmSendType sendtype, char verbose, char *pitdate) { @@ -697,7 +835,7 @@ int tsm_restorefile(dsUint32_t sesshandle, char *fsname, char *filename, dataBlk.numBytes = 0; rc = dsmGetObj(sesshandle, &cbdata.objId, &dataBlk); while(rc == DSM_RC_MORE_DATA) { - if(write_full(STDOUT_FILENO, dataBlk.bufferPtr, dataBlk.numBytes) < 0) { + if(rw_full(STDOUT_FILENO, dataBlk.bufferPtr, dataBlk.numBytes) < 0) { perror("tsmpipe: write"); return 0; } @@ -708,7 +846,7 @@ int tsm_restorefile(dsUint32_t sesshandle, char *fsname, char *filename, tsm_printerr(sesshandle, rc, "dsmGetObj/dsmGetData failed"); return 0; } - if(write_full(STDOUT_FILENO, dataBlk.bufferPtr, dataBlk.numBytes) < 0) { + if(rw_full(STDOUT_FILENO, dataBlk.bufferPtr, dataBlk.numBytes) < 0) { perror("tsmpipe: write"); return 0; } @@ -894,7 +1032,7 @@ int main(int argc, char *argv[]) { int c; extern int optind, optopt; extern char *optarg; - char archmode=0, backmode=0, create=0, xtract=0, delete=0, verbose=0; + char archmode=0, backmode=0, create=0, xtract=0, delete=0, verbose=0, info=0; char list=0; char *space=NULL, *filename=NULL, *lenstr=NULL, *desc=NULL, *pitdate=NULL; char *options=NULL; @@ -902,11 +1040,14 @@ int main(int argc, char *argv[]) { dsUint32_t sesshandle; dsmSendType sendtype; - while ((c = getopt(argc, argv, "hABcxdtvs:f:l:D:O:P:")) != -1) { + while ((c = getopt(argc, argv, "hiABcxdtvs:f:l:D:O:P:")) != -1) { switch(c) { case 'h': usage(); exit(1); + case 'i': + info = 1; + break; case 'A': archmode = 1; break; @@ -955,31 +1096,31 @@ int main(int argc, char *argv[]) { } } - if(archmode+backmode != 1) { - fprintf(stderr, "tsmpipe: ERROR: Must give one of -A or -B\n"); + if(archmode+backmode+info != 1) { + fprintf(stderr, "tsmpipe: ERROR: Must give one of -i, -A or -B\n"); exit(1); } - if(create+xtract+delete+list != 1) { + if(create+xtract+delete+list+info != 1) { fprintf(stderr, "tsmpipe: ERROR: Must give one of -c, -x, -d or -t\n"); exit(1); } - if(!space) { + if(!info && !space) { fprintf(stderr, "tsmpipe: ERROR: Must give -s filespacename\n"); exit(1); } - if(!filename) { + if(!info && !filename) { fprintf(stderr, "tsmpipe: ERROR: Must give -f filename\n"); exit(1); } - if(create && !lenstr) { + if(!info && create && !lenstr) { fprintf(stderr, "tsmpipe: ERROR: Must give -l length with -c\n"); exit(1); } - if(!create && lenstr) { + if(!info && !create && lenstr) { fprintf(stderr, "tsmpipe: ERROR: -l length useless without -c\n"); exit(1); } - if(!archmode && desc) { + if(!info && !archmode && desc) { fprintf(stderr, "tsmpipe: ERROR: -D desc useless without -A\n"); exit(1); } @@ -1017,6 +1158,11 @@ int main(int argc, char *argv[]) { fprintf(stderr, "tsmpipe: Session initiated\n"); } + if(info) { + fprintf(stdout,"info"); + exit(0); + } + if(create) { if(!tsm_regfs(sesshandle, space)) { exit(4); @@ -1064,7 +1210,6 @@ int main(int argc, char *argv[]) { return(0); } - /* vim:ts=4:sw=4:et:cindent */