Rework
This commit is contained in:
parent
f0da66ef81
commit
80677a35a9
@ -4,13 +4,26 @@ CC=gcc
|
||||
CFLAGS=-g -W -Wall -Wextra -O -I$(TSMAPIDIR)
|
||||
LDFLAGS=
|
||||
|
||||
FILES=tsmpipe.c
|
||||
|
||||
|
||||
all: tsmpipe
|
||||
|
||||
tsmpipe: $(FILES:.c=.o)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(FILES:.c=.o) $(TSMLIB) -lm
|
||||
tsmpipe: tsmpipe.o lib/dsmobjects.o lib/dsmsession.o lib/dsmlist.o lib/dsmsendrecv.o
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $+ $(TSMLIB) -lm
|
||||
|
||||
tsmpipe.c:
|
||||
echo 'hello'
|
||||
$(CC) $(CFLAGS) -c -o $(@:.c=.o) $@ $(TSMLIB)
|
||||
|
||||
lib/dsmlist:
|
||||
$(CC) $(CFLAGS) -c -o lib/$@.o lib/$@.c $(TSMLIB)
|
||||
|
||||
lib/dsmsendrecv:
|
||||
$(CC) $(CFLAGS) -c -o lib/$@.o lib/$@.c $(TSMLIB)
|
||||
|
||||
lib/dsmsession:
|
||||
$(CC) $(CFLAGS) -c -o lib/$@.o lib/$@.c $(TSMLIB)
|
||||
|
||||
lib/dsmobjects:
|
||||
$(CC) $(CFLAGS) -c -o lib/$@.o lib/$@.c $(TSMLIB)
|
||||
|
||||
clean:
|
||||
rm tsmpipe *.o
|
||||
rm tsmpipe *.o lib/*.o
|
||||
|
114
lib/dsmlist.c
Normal file
114
lib/dsmlist.c
Normal file
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* This function will list the contents that we have stored with tsmpipe
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dsmrc.h"
|
||||
#include "dsmapitd.h"
|
||||
#include "../tsmpipe.h"
|
||||
|
||||
dsBool_t headerPrinted=bFalse; // Have we rendered the heading row yet
|
||||
|
||||
extern char *dsmDateToStr(dsmDate date);
|
||||
extern char *dsmObjnameToStr(dsmObjName objName);
|
||||
extern double dsmSizeToNum(dsStruct64_t dsStruct64);
|
||||
extern dsmObjName dsmNameToObjname(char *fsname, char *filename, int verbose);
|
||||
extern dsInt16_t tsm_queryfile(dsUint32_t sesshandle, dsmObjName *objName, char *description, dsmSendType sendtype, char verbose, tsm_query_callback usercb, void * userdata, char *pitdate, int querytype);
|
||||
|
||||
/*
|
||||
* Our Callback to show what is in TSM
|
||||
*/
|
||||
int tsm_listfile_cb(dsmQueryType qType, DataBlk *qResp, void *userdata) {
|
||||
char stor[1]="?";
|
||||
char state[2]="??";
|
||||
char ced[3]="---";
|
||||
|
||||
qryRespBackupData respBackup;
|
||||
qryRespArchiveData respArchive;
|
||||
|
||||
if (userdata != NULL ) {
|
||||
fprintf(stderr, "tsm_listfile_cb: Internal error: userdate != NULL");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (! headerPrinted++)
|
||||
printf("%40s %2s %s %3s %19s %10s %s\n",
|
||||
"NAME",
|
||||
"ST",
|
||||
"L",
|
||||
"CED",
|
||||
"BACKUP",
|
||||
"EST SIZE",
|
||||
"ID"
|
||||
);
|
||||
|
||||
if (qType == qtArchive) {
|
||||
memset(&respArchive,0x00,sizeof(qryRespArchiveData));
|
||||
qryRespArchiveData *qr = (void *) qResp->bufferPtr;
|
||||
respArchive = *qr;
|
||||
|
||||
|
||||
} else if (qType ==qtBackup) {
|
||||
memset(&respBackup,0x00,sizeof(qryRespBackupData));
|
||||
qryRespBackupData *qr = (void *) qResp->bufferPtr;
|
||||
respBackup = *qr;
|
||||
|
||||
// The Object Status
|
||||
switch (respBackup.objName.objType) {
|
||||
case (DSM_OBJ_FILE) : strcpy(state,"F"); break;
|
||||
case (DSM_OBJ_DIRECTORY) : strcpy(state,"D"); break;
|
||||
default : strcpy(state,"?");
|
||||
}
|
||||
|
||||
switch (respBackup.objState) {
|
||||
case (DSM_ACTIVE) : strcat(state,"A"); break;
|
||||
case (DSM_INACTIVE) : strcat(state,"I"); break;
|
||||
default : strcat(state,"?");
|
||||
}
|
||||
|
||||
// Location
|
||||
switch (respBackup.mediaClass) {
|
||||
case (MEDIA_FIXED) : strcpy(stor,"D"); break;
|
||||
case (MEDIA_LIBRARY) : strcpy(stor,"T"); break;
|
||||
default : strcpy(stor,"?");
|
||||
}
|
||||
|
||||
// Compression, Encryption, De-Duplication
|
||||
strcpy(ced,(respBackup.compressType == DSM_OBJ_COMPRESSED_YES ? "C" :
|
||||
(respBackup.compressType == DSM_OBJ_COMPRESSED_NO ? "-" : "?")));
|
||||
|
||||
strcat(ced,(respBackup.encryptionType & DSM_ENCRYPT_CLIENTENCRKEY ? "C" :
|
||||
(respBackup.encryptionType & DSM_ENCRYPT_USER ? "U" : "-")));
|
||||
|
||||
strcat(ced,respBackup.clientDeduplicated ? "D" : "-");
|
||||
|
||||
} else {
|
||||
fprintf(stderr,"tsm_listfile_cb: Internal error: Unknown qType %d\n",qType);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%40s|%2s|%s|%3s|%19s|%7.3f MB|%u-%u\n",dsmObjnameToStr(respBackup.objName),state,stor,ced,dsmDateToStr(respBackup.insDate),dsmSizeToNum(respBackup.sizeEstimate),respBackup.objId.hi,respBackup.objId.lo);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* List objects that are in TSM
|
||||
*/
|
||||
int tsm_listfile(dsUint32_t sesshandle, char *fsname, char *filename, char *description, dsmSendType sendtype, char verbose, char *pitdate) {
|
||||
dsInt16_t rc=0;
|
||||
dsmObjName objName;
|
||||
|
||||
objName = dsmNameToObjname(fsname,filename,verbose);
|
||||
|
||||
rc = tsm_queryfile(sesshandle, &objName, description, sendtype, verbose, tsm_listfile_cb, NULL, pitdate, DSM_ANY_MATCH);
|
||||
|
||||
if (rc != DSM_RC_OK && rc != DSM_RC_ABORT_NO_MATCH)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
143
lib/dsmobjects.c
Normal file
143
lib/dsmobjects.c
Normal file
@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Date manipulations functions for tsmpipe
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dsmapitd.h"
|
||||
|
||||
/*
|
||||
* This function will take a string date entered and convert that to a TSM
|
||||
* date
|
||||
*
|
||||
* The date is passed to this function in the format mmddYYYY
|
||||
*/
|
||||
dsmDate dsmStrToDate(char *s,int verbose) {
|
||||
dsmDate *date;
|
||||
dsUint32_t x;
|
||||
|
||||
date = (dsmDate*)malloc(sizeof(dsmDate));
|
||||
|
||||
if (date==NULL) {
|
||||
perror("Arg, out of memory?");
|
||||
exit(255);
|
||||
}
|
||||
|
||||
memset(date,0x00,sizeof(dsmDate));
|
||||
|
||||
if (verbose)
|
||||
printf("dsmStrToDate: Date String: %s\n", s);
|
||||
|
||||
/* if user key in some inputs */
|
||||
if (s[0] != '\0') {
|
||||
x = atol(s);
|
||||
date->month = x / 1000000;
|
||||
|
||||
x %= 1000000;
|
||||
date->day = x / 10000;
|
||||
date->year = x % 10000;
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
printf("dsmStrToDate: date = %d, month = %d, year = %d\n", date->day, date->month, date->year);
|
||||
|
||||
return *date;
|
||||
}
|
||||
|
||||
/* Display the dsmDate value as a string */
|
||||
char *dsmDateToStr(dsmDate date) {
|
||||
char *s;
|
||||
|
||||
s = malloc(19);
|
||||
|
||||
if (s==NULL) {
|
||||
perror("Arg, out of memory?");
|
||||
exit(255);
|
||||
}
|
||||
|
||||
memset(s,0x00,sizeof(s));
|
||||
|
||||
sprintf(s,"%02i/%02i/%04i %02i:%02i:%02i",
|
||||
(dsInt16_t)date.day,
|
||||
(dsInt16_t)date.month,
|
||||
date.year,
|
||||
(dsInt16_t)date.hour,
|
||||
(dsInt16_t)date.minute,
|
||||
(dsInt16_t)date.second);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
dsmObjName dsmNameToObjname(char *fsname, char *filename, int verbose) {
|
||||
dsmObjName *objname;
|
||||
char *p;
|
||||
|
||||
objname = (dsmObjName*)malloc(sizeof(dsmObjName));
|
||||
|
||||
if (objname==NULL) {
|
||||
perror("Arg, out of memory?");
|
||||
exit(255);
|
||||
}
|
||||
|
||||
memset(objname,0x00,sizeof(dsmObjName));
|
||||
|
||||
if (verbose)
|
||||
fprintf(stderr,"dsmNameToObjname: FS: %s Filename: %s\n",fsname,filename);
|
||||
|
||||
/* fs == "/filesystem", hl == "/directory/path", ll == "/filename" */
|
||||
strcpy(objname->fs,fsname);
|
||||
|
||||
p = strrchr(filename, '/');
|
||||
|
||||
if (p) {
|
||||
*p = '\0';
|
||||
|
||||
if (*filename && *filename != '/')
|
||||
strcpy(objname->hl, "/");
|
||||
|
||||
strcpy(objname->hl,filename);
|
||||
sprintf(objname->ll,"/%s",p+1);
|
||||
|
||||
} else {
|
||||
if (*filename && *filename != '/')
|
||||
strcpy(objname->ll, "/");
|
||||
|
||||
strcat(objname->ll,filename);
|
||||
}
|
||||
|
||||
objname->objType = DSM_OBJ_FILE;
|
||||
|
||||
return *objname;
|
||||
}
|
||||
|
||||
char *dsmObjnameToStr(dsmObjName objName) {
|
||||
char *s;
|
||||
|
||||
s = malloc(sizeof(dsmObjName));
|
||||
|
||||
if (s==NULL) {
|
||||
perror("Arg, out of memory?");
|
||||
exit(255);
|
||||
}
|
||||
|
||||
memset(s,0x00,sizeof(s));
|
||||
|
||||
sprintf(s,"%s%s%s",objName.fs,objName.hl,objName.ll);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
double dsmSizeToNum(dsStruct64_t dsStruct64) {
|
||||
unsigned long long filesize=0;
|
||||
|
||||
filesize = 0x00;
|
||||
|
||||
filesize = dsStruct64.hi;
|
||||
filesize <<= 32;
|
||||
filesize |= dsStruct64.lo;
|
||||
|
||||
// Return number in MB
|
||||
return (float)filesize/1024/1024;
|
||||
}
|
445
lib/dsmsendrecv.c
Normal file
445
lib/dsmsendrecv.c
Normal file
@ -0,0 +1,445 @@
|
||||
/*
|
||||
* The recommended buffer size is n*TCPBUFFLEN - 4 bytes.
|
||||
* To get your buffer size, do: dsmc query options|grep TCPBUF
|
||||
* 32kB seems to be the new default, 31kB was the old.
|
||||
*
|
||||
* An additional factor is the pipe buffer size. Since we don't do threading
|
||||
* (yet), we hide a little bit of latency if we don't read more than the pipe
|
||||
* buffer can hold at a time. On Linux 2.6 this is 64kB.
|
||||
*
|
||||
* So, I would recommend a BUFLEN of 64kB if your TCPBUFLEN is above the
|
||||
* 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 64*1024-4.
|
||||
*/
|
||||
|
||||
#define BUFLEN (64*1024-4)
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "dsmrc.h"
|
||||
#include "dsmapitd.h"
|
||||
#include "dsmapifp.h"
|
||||
|
||||
#include "../tsmpipe.h"
|
||||
|
||||
extern dsBool_t compressEnabled;
|
||||
|
||||
extern void tsm_printerr(dsUint32_t dsmHandle, dsInt16_t rc, char *str);
|
||||
extern char *dsmObjnameToStr(dsmObjName objName);
|
||||
extern double dsmSizeToNum(dsStruct64_t dsStruct64);
|
||||
extern dsmObjName dsmNameToObjname(char *fsname, char *filename, int verbose);
|
||||
extern dsInt16_t tsm_queryfile(dsUint32_t dsmHandle, dsmObjName *objName, char *description, dsmSendType sendtype, char verbose, tsm_query_callback usercb, void * userdata, char *pitdate, int querytype);
|
||||
|
||||
int tsm_matchone_cb(dsmQueryType qType, DataBlk *qResp, void * userdata) {
|
||||
struct matchone_cb_data *cbdata = userdata;
|
||||
|
||||
cbdata->numfound++;
|
||||
|
||||
if (qType == qtArchive) {
|
||||
qryRespArchiveData *qr = (void *) qResp->bufferPtr;
|
||||
|
||||
cbdata->objId = qr->objId;
|
||||
|
||||
} else if(qType == qtBackup) {
|
||||
qryRespBackupData *qr = (void *) qResp->bufferPtr;
|
||||
|
||||
cbdata->objId = qr->objId;
|
||||
cbdata->copyGroup = qr->copyGroup;
|
||||
|
||||
} else {
|
||||
fprintf(stderr,"tsm_matchone_cb: Internal error: Unknown qType %d\n",qType);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (cbdata->numfound > 1) {
|
||||
fprintf(stderr,"tsmpipe: FAILED: The file specification matched multiple files.\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
ssize_t len;
|
||||
|
||||
if (fd == STDIN_FILENO) {
|
||||
len = read(fd,buf+done,count);
|
||||
|
||||
} else if (fd == STDOUT_FILENO) {
|
||||
len = write(fd,buf+done,count);
|
||||
|
||||
} else {
|
||||
fprintf(stderr,"rw_full: rw_full: Unknown FD\n");
|
||||
exit(4);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/* Register a filespace in TSM */
|
||||
int tsm_regfs(dsUint32_t dsmHandle, char *fsname) {
|
||||
dsInt16_t rc=0;
|
||||
regFSData regFS;
|
||||
|
||||
memset(®FS, 0, sizeof(regFS));
|
||||
|
||||
regFS.fsName = fsname;
|
||||
regFS.fsType = "TSMPIPE";
|
||||
|
||||
rc = dsmRegisterFS(dsmHandle,®FS);
|
||||
|
||||
if (rc != DSM_RC_OK && rc != DSM_RC_FS_ALREADY_REGED) {
|
||||
tsm_printerr(dsmHandle,rc,"tsm_regfs: dsmRegisterFS failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Send data to TSM for storage */
|
||||
int tsm_sendfile(dsUint32_t dsmHandle, char *fsname, char *filename, off_t length, char *description, dsmSendType sendtype, char verbose) {
|
||||
char *buffer;
|
||||
dsInt16_t rc=0;
|
||||
dsmObjName objName;
|
||||
mcBindKey mcBindKey;
|
||||
ObjAttr objAttr;
|
||||
DataBlk dataBlk;
|
||||
sndArchiveData archData, *archDataP=NULL;
|
||||
ssize_t nbytes;
|
||||
dsmEndSendObjExIn_t dsmEndSendObjExIn;
|
||||
dsmEndSendObjExOut_t dsmEndSendObjExOut;
|
||||
dsUint16_t reason=0;
|
||||
|
||||
buffer = malloc(BUFLEN);
|
||||
if (buffer==NULL) {
|
||||
perror("tsm_sendfile: Argh, out of memory?");
|
||||
exit(255);
|
||||
}
|
||||
|
||||
// Register our filespace
|
||||
if (! tsm_regfs(dsmHandle,fsname))
|
||||
exit(3);
|
||||
|
||||
// Warn if we wont do compression
|
||||
if (verbose && compressEnabled && length <= DSM_MIN_COMPRESS_SIZE)
|
||||
fprintf(stderr,"tsm_sendfile: WARNING: Size (%i) too small for compression/de-duplication, even though it is enabled",(int)length);
|
||||
|
||||
// Start a Transaction
|
||||
rc = dsmBeginTxn(dsmHandle);
|
||||
if (rc != DSM_RC_OK) {
|
||||
tsm_printerr(dsmHandle,rc,"tsm_sendfile: dsmBeginTxn failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(&objName,0x00,sizeof(objName));
|
||||
objName = dsmNameToObjname(fsname,filename,verbose);
|
||||
|
||||
if (verbose)
|
||||
fprintf(stderr,"tsm_sendfile: Starting to send stdin as %s\n",dsmObjnameToStr(objName));
|
||||
|
||||
memset(&mcBindKey,0x00,sizeof(mcBindKey));
|
||||
mcBindKey.stVersion = mcBindKeyVersion;
|
||||
rc = dsmBindMC(dsmHandle,&objName,sendtype,&mcBindKey);
|
||||
if (rc != DSM_RC_OK) {
|
||||
tsm_printerr(dsmHandle,rc,"tsm_sendfile: dsmBindMC failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (verbose > 1) {
|
||||
char *cgdest=NULL;
|
||||
|
||||
fprintf(stderr,"tsm_sendfile: Bound to Management Class: %s\n",mcBindKey.mcName);
|
||||
|
||||
if ((sendtype == stArchiveMountWait || sendtype == stArchive) && mcBindKey.archive_cg_exists) {
|
||||
cgdest = mcBindKey.archive_copy_dest;
|
||||
|
||||
} else if(mcBindKey.backup_cg_exists) {
|
||||
cgdest = mcBindKey.backup_copy_dest;
|
||||
}
|
||||
|
||||
if (cgdest)
|
||||
fprintf(stderr,"tsm_sendfile: Destination Copy Group: %s\n",cgdest);
|
||||
}
|
||||
|
||||
memset(&objAttr,0x00,sizeof(ObjAttr));
|
||||
objAttr.stVersion = ObjAttrVersion;
|
||||
*objAttr.owner = '\0';
|
||||
objAttr.sizeEstimate.hi = length >> 32;
|
||||
objAttr.sizeEstimate.lo = length & ~0U;
|
||||
objAttr.objCompressed = bFalse;
|
||||
// @todo Could we use the objinfo field?
|
||||
|
||||
if (sendtype == stArchiveMountWait || sendtype == stArchive) {
|
||||
memset(&archData,0x00,sizeof(sndArchiveData));
|
||||
|
||||
archData.stVersion = sndArchiveDataVersion;
|
||||
archData.descr = description;
|
||||
|
||||
archDataP = &archData;
|
||||
}
|
||||
|
||||
rc = dsmSendObj(dsmHandle,sendtype,archDataP,&objName,&objAttr,NULL);
|
||||
if (rc != DSM_RC_OK) {
|
||||
tsm_printerr(dsmHandle,rc,"tsm_sendfile: dsmSendObj failed");
|
||||
return(0);
|
||||
}
|
||||
|
||||
memset(&dataBlk,0x00,sizeof(DataBlk));
|
||||
dataBlk.stVersion = DataBlkVersion;
|
||||
|
||||
while(1) {
|
||||
nbytes = rw_full(STDIN_FILENO,buffer,BUFLEN);
|
||||
|
||||
if (nbytes < 0) {
|
||||
perror("tsmpipe: read");
|
||||
return 0;
|
||||
} else if (nbytes == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
dataBlk.bufferLen = nbytes;
|
||||
dataBlk.numBytes = 0;
|
||||
dataBlk.bufferPtr = buffer;
|
||||
|
||||
rc = dsmSendData(dsmHandle,&dataBlk);
|
||||
|
||||
if (rc != DSM_RC_OK && rc != DSM_RC_COMPRESS_GREW) {
|
||||
tsm_printerr(dsmHandle,rc,"tsm_senfile: dsmSendData failed");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
memset(&dsmEndSendObjExIn,0x00,sizeof(dsmEndSendObjExIn_t));
|
||||
memset(&dsmEndSendObjExOut,0x00,sizeof(dsmEndSendObjExOut_t));
|
||||
|
||||
dsmEndSendObjExIn.stVersion = dsmEndSendObjExInVersion;
|
||||
dsmEndSendObjExIn.dsmHandle = dsmHandle;
|
||||
dsmEndSendObjExOut.stVersion = dsmEndSendObjExOutVersion;
|
||||
|
||||
if ((rc = dsmEndSendObjEx(&dsmEndSendObjExIn,&dsmEndSendObjExOut)) != DSM_RC_OK) {
|
||||
tsm_printerr(dsmHandle,rc,"tsm_sendfile: dsmEndSendObjEx failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = dsmEndTxn(dsmHandle,DSM_VOTE_COMMIT,&reason);
|
||||
if (rc == DSM_RC_CHECK_REASON_CODE || (rc == DSM_RC_OK && reason != DSM_RC_OK)) {
|
||||
tsm_printerr(dsmHandle,reason,"tsm_sendfile: dsmEndTxn failed, reason");
|
||||
return 0;
|
||||
|
||||
} else if(rc != DSM_RC_OK) {
|
||||
tsm_printerr(dsmHandle,rc,"tsm_sendfile: dsmEndTxn failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
printf("Total bytes sent: %5.3f\n",dsmSizeToNum(dsmEndSendObjExOut.totalBytesSent));
|
||||
|
||||
if (dsmEndSendObjExOut.objDeduplicated)
|
||||
printf("Deduplicated size: %5.3f\n",dsmSizeToNum(dsmEndSendObjExOut.totalDedupSize));
|
||||
if (dsmEndSendObjExOut.objCompressed)
|
||||
printf("Compressed size: %5.3f\n",dsmSizeToNum(dsmEndSendObjExOut.totalCompressSize));
|
||||
if (dsmSizeToNum(dsmEndSendObjExOut.totalLFBytesSent))
|
||||
printf("LAN-free bytes sentsize: %5.3f\n",dsmSizeToNum(dsmEndSendObjExOut.totalLFBytesSent));
|
||||
|
||||
if (dsmEndSendObjExOut.encryptionType) {
|
||||
printf("Encryption: %s\n",dsmEndSendObjExOut.encryptionType & DSM_ENCRYPT_CLIENTENCRKEY ? "CLIENTENCRKEY" : dsmEndSendObjExOut.encryptionType & DSM_ENCRYPT_USER ? "USER" : "NO");
|
||||
printf("Encryption Strength: %s\n",dsmEndSendObjExOut.encryptionType & DSM_ENCRYPT_AES_128BIT ? "AES_128BIT" : dsmEndSendObjExOut.encryptionType & DSM_ENCRYPT_DES_56BIT ? "DES_56BIT" : "NONE");
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Get data from TSM for restore */
|
||||
int tsm_restorefile(dsUint32_t dsmHandle, char *fsname, char *filename, char *description, dsmSendType sendtype, char verbose, char *pitdate) {
|
||||
dsInt16_t rc=0;
|
||||
struct matchone_cb_data cbdata;
|
||||
dsmObjName objName;
|
||||
dsmGetList getList;
|
||||
dsmGetType getType;
|
||||
DataBlk dataBlk;
|
||||
|
||||
objName = dsmNameToObjname(fsname,filename,verbose);
|
||||
|
||||
if (verbose)
|
||||
fprintf(stderr,"tsm_restorefile: Starting to receive %s via stdin\n",dsmObjnameToStr(objName));
|
||||
|
||||
memset(&cbdata,0x00,sizeof(cbdata));
|
||||
cbdata.numfound = 0;
|
||||
|
||||
// Retrieve a list based on the PITDATE or if no PITDATE, the last ACTIVE
|
||||
rc = tsm_queryfile(dsmHandle,&objName,description,sendtype,verbose,tsm_matchone_cb,&cbdata,pitdate,pitdate ? DSM_ANY_MATCH : DSM_ACTIVE);
|
||||
|
||||
if (rc != DSM_RC_OK)
|
||||
return 0;
|
||||
|
||||
if (cbdata.numfound == 0) {
|
||||
fprintf(stderr,"tsm_restorefile: FAILED: The file specification did not match any file.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(&getList,0x00,sizeof(dsmGetList));
|
||||
getList.stVersion = dsmGetListVersion;
|
||||
getList.numObjId = 1;
|
||||
getList.objId = &cbdata.objId;
|
||||
getList.partialObjData = NULL;
|
||||
|
||||
if (sendtype == stArchiveMountWait || sendtype == stArchive) {
|
||||
getType = gtArchive;
|
||||
} else {
|
||||
getType = gtBackup;
|
||||
}
|
||||
|
||||
rc = dsmBeginGetData(dsmHandle,bTrue,getType,&getList);
|
||||
if (rc != DSM_RC_OK) {
|
||||
tsm_printerr(dsmHandle,rc,"tsm_restorefile: dsmBeginGetData failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(&dataBlk,0x00,sizeof(DataBlk));
|
||||
dataBlk.stVersion = DataBlkVersion;
|
||||
dataBlk.bufferPtr = malloc(BUFLEN);
|
||||
if (!dataBlk.bufferPtr) {
|
||||
perror("tsm_restorefile: malloc");
|
||||
return 0;
|
||||
}
|
||||
|
||||
dataBlk.bufferLen = BUFLEN;
|
||||
dataBlk.numBytes = 0;
|
||||
|
||||
rc = dsmGetObj(dsmHandle,&cbdata.objId,&dataBlk);
|
||||
|
||||
while (rc == DSM_RC_MORE_DATA) {
|
||||
if (rw_full(STDOUT_FILENO,dataBlk.bufferPtr,dataBlk.numBytes) < 0) {
|
||||
perror("tsm_restorefile: write");
|
||||
return 0;
|
||||
}
|
||||
|
||||
dataBlk.numBytes = 0;
|
||||
rc = dsmGetData(dsmHandle,&dataBlk);
|
||||
}
|
||||
|
||||
if (rc != DSM_RC_FINISHED) {
|
||||
tsm_printerr(dsmHandle,rc,"tsm_restorefile: dsmGetObj/dsmGetData failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rw_full(STDOUT_FILENO,dataBlk.bufferPtr,dataBlk.numBytes) < 0) {
|
||||
perror("tsm_restorefile: write");
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = dsmEndGetObj(dsmHandle);
|
||||
if (rc != DSM_RC_OK) {
|
||||
tsm_printerr(dsmHandle,rc,"tsm_restorefile: dsmEndGetObj failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = dsmEndGetData(dsmHandle);
|
||||
if (rc != DSM_RC_OK) {
|
||||
tsm_printerr(dsmHandle,rc,"tsm_restorefile: dsmEndGetData failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Delete data in TSM */
|
||||
int tsm_deletefile(dsUint32_t dsmHandle, char *fsname, char *filename, char *description, dsmSendType sendtype, char verbose) {
|
||||
dsInt16_t rc=0;
|
||||
dsUint16_t reason=0;
|
||||
dsmDelInfo *dInfoP;
|
||||
dsmDelType dType;
|
||||
struct matchone_cb_data cbdata;
|
||||
delArch daInfo;
|
||||
delBack dbInfo;
|
||||
dsmObjName objName;
|
||||
|
||||
objName = dsmNameToObjname(fsname,filename,verbose);
|
||||
|
||||
if (verbose)
|
||||
fprintf(stderr,"tsm_deletefile: Deleting file %s\n",dsmObjnameToStr(objName));
|
||||
|
||||
cbdata.numfound = 0;
|
||||
|
||||
rc = tsm_queryfile(dsmHandle,&objName,description,sendtype,verbose,tsm_matchone_cb,&cbdata,NULL,DSM_ACTIVE);
|
||||
if (rc != DSM_RC_OK) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cbdata.numfound == 0) {
|
||||
fprintf(stderr,"tsm_deletefile: FAILED: The file specification did not match any file.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sendtype == stArchiveMountWait || sendtype == stArchive) {
|
||||
dType = dtArchive;
|
||||
|
||||
daInfo.stVersion = delArchVersion;
|
||||
daInfo.objId = cbdata.objId;
|
||||
|
||||
dInfoP = (dsmDelInfo *) &daInfo;
|
||||
} else {
|
||||
dType = dtBackup;
|
||||
|
||||
dbInfo.stVersion = delBackVersion;
|
||||
dbInfo.objNameP = &objName;
|
||||
dbInfo.copyGroup = cbdata.copyGroup;
|
||||
|
||||
dInfoP = (dsmDelInfo *) &dbInfo;
|
||||
}
|
||||
|
||||
rc = dsmBeginTxn(dsmHandle);
|
||||
if (rc != DSM_RC_OK) {
|
||||
tsm_printerr(dsmHandle,rc,"tsm_deletefile: dsmBeginTxn failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = dsmDeleteObj(dsmHandle,dType,*dInfoP);
|
||||
if (rc != DSM_RC_OK) {
|
||||
tsm_printerr(dsmHandle,rc,"tsm_deletefile: dsmDeleteObj failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = dsmEndTxn(dsmHandle,DSM_VOTE_COMMIT,&reason);
|
||||
if (rc == DSM_RC_CHECK_REASON_CODE || (rc == DSM_RC_OK && reason != DSM_RC_OK)) {
|
||||
tsm_printerr(dsmHandle,reason,"tsm_deletefile: dsmEndTxn failed, reason");
|
||||
return 0;
|
||||
|
||||
} else if (rc != DSM_RC_OK) {
|
||||
tsm_printerr(dsmHandle,rc,"tsm_deletefile: dsmEndTxn failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
369
lib/dsmsession.c
Normal file
369
lib/dsmsession.c
Normal file
@ -0,0 +1,369 @@
|
||||
/*
|
||||
* This function will set up a session to the TSM server and return the
|
||||
* session handler
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dsmrc.h"
|
||||
#include "dsmapitd.h"
|
||||
#include "dsmapifp.h"
|
||||
|
||||
#include "../tsmpipe.h"
|
||||
|
||||
dsBool_t compressEnabled=bFalse; // Is compression enabled
|
||||
|
||||
extern char *dsmDateToStr(dsmDate date);
|
||||
extern dsmDate dsmStrToDate(char *s,int verbose);
|
||||
extern char *dsmObjnameToStr(dsmObjName objName);
|
||||
|
||||
/* Print out TSM Error Code */
|
||||
void tsm_printerr(dsUint32_t dsmHandle, dsInt16_t rc, char *str) {
|
||||
char rcStr[DSM_MAX_RC_MSG_LENGTH];
|
||||
|
||||
if (rc == DSM_RC_WILL_ABORT) {
|
||||
dsUint16_t reason;
|
||||
|
||||
rc = dsmEndTxn(dsmHandle, DSM_VOTE_COMMIT, &reason);
|
||||
|
||||
if (rc == DSM_RC_CHECK_REASON_CODE)
|
||||
rc = reason;
|
||||
}
|
||||
|
||||
dsmRCMsg(dsmHandle,rc,rcStr);
|
||||
|
||||
fprintf(stderr, "tsmpipe: %s\n (rc=%s)\n",str,rcStr);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
memset(&apiLibVer,0x00,sizeof(dsmApiVersionEx));
|
||||
apiLibVer.stVersion = apiVersionExVer;
|
||||
dsmQueryApiVersionEx(&apiLibVer);
|
||||
|
||||
apiVersion = (10000 * apiLibVer.version) + (1000 * apiLibVer.release) + (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 than the application version (%d.%d.%d.%d)\n",
|
||||
apiLibVer.version,
|
||||
apiLibVer.release,
|
||||
apiLibVer.level,
|
||||
apiLibVer.subLevel,
|
||||
DSM_API_VERSION,
|
||||
DSM_API_RELEASE,
|
||||
DSM_API_LEVEL,
|
||||
DSM_API_SUBLEVEL);
|
||||
|
||||
printf("Please upgrade the API accordingly.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Initialise a session to the TSM server */
|
||||
dsUint32_t tsm_initsess(char *options) {
|
||||
dsInt16_t rc=0;
|
||||
dsUint32_t dsmHandle=0;
|
||||
dsmApiVersionEx applApi;
|
||||
dsmInitExIn_t initIn;
|
||||
dsmInitExOut_t initOut;
|
||||
optStruct dsmOpt;
|
||||
ApiSessInfo dsmSessInfo;
|
||||
|
||||
if (! tsm_checkapi()) {
|
||||
exit(2);
|
||||
}
|
||||
|
||||
memset(&applApi,0x00,sizeof(dsmApiVersionEx));
|
||||
applApi.stVersion = apiVersionExVer;
|
||||
applApi.version = DSM_API_VERSION;
|
||||
applApi.release = DSM_API_RELEASE;
|
||||
applApi.level = DSM_API_LEVEL;
|
||||
applApi.subLevel = DSM_API_SUBLEVEL;
|
||||
|
||||
memset(&initIn,0x00,sizeof(dsmInitExIn_t));
|
||||
initIn.stVersion = dsmInitExInVersion;
|
||||
initIn.apiVersionExP = &applApi;
|
||||
initIn.clientNodeNameP = NULL;
|
||||
initIn.clientOwnerNameP = NULL;
|
||||
initIn.clientPasswordP = NULL;
|
||||
initIn.applicationTypeP = NULL;
|
||||
initIn.configfile = NULL;
|
||||
initIn.options = options;
|
||||
initIn.userNameP = NULL;
|
||||
initIn.userPasswordP = NULL;
|
||||
//initIn.dirDelimiter = dirDelimiter;
|
||||
//initIn.useUnicode = useUnicode;
|
||||
//initIn.bEncryptKeyEnabled = encrypt;
|
||||
//initIn.encryptionPasswordP = encryptKey;
|
||||
|
||||
memset(&initOut,0x00,sizeof(dsmInitExOut_t));
|
||||
initOut.stVersion = dsmInitExOutVersion;
|
||||
|
||||
rc = dsmInitEx(&dsmHandle, &initIn, &initOut);
|
||||
|
||||
/* If the TSM password has expired, change it. */
|
||||
if (rc == DSM_RC_REJECT_VERIFIER_EXPIRED) {
|
||||
rc = dsmChangePW(dsmHandle,NULL,NULL);
|
||||
|
||||
if (rc != DSM_RC_OK) {
|
||||
tsm_printerr(dsmHandle,rc,"dsmChangePW failed");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} else if (rc != DSM_RC_OK) {
|
||||
tsm_printerr(dsmHandle, rc, "dsmInitEx failed");
|
||||
dsmTerminate(dsmHandle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Make sure if we have compression enabled, that we also have COMPRESSAlways YES
|
||||
memset(&dsmOpt,0x00,sizeof(dsmOpt));
|
||||
rc = dsmQuerySessOptions(dsmHandle, &dsmOpt);
|
||||
|
||||
memset(&dsmSessInfo,0x00,sizeof(ApiSessInfo));
|
||||
dsmSessInfo.stVersion = ApiSessInfoVersion; /* Init struct version */
|
||||
rc = dsmQuerySessInfo(dsmHandle, &dsmSessInfo);
|
||||
|
||||
rc = 1;
|
||||
switch (dsmSessInfo.compression) {
|
||||
case COMPRESS_YES : compressEnabled = bTrue; break;
|
||||
case COMPRESS_NO : compressEnabled = bFalse; break;
|
||||
case COMPRESS_CD : compressEnabled = dsmOpt.compression; break;
|
||||
default : rc=0;
|
||||
}
|
||||
|
||||
if (!rc || (compressEnabled && ! dsmOpt.compressalways)) {
|
||||
fprintf(stderr,!rc ? "Error Querying Session Capabilities" : "Error, COMPRESSion is ENABLED, but not COMPRESSAlways Yes\n");
|
||||
fprintf(stderr,"\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return dsmHandle;
|
||||
}
|
||||
|
||||
/* List objects that are in TSM */
|
||||
void tsm_sessioninfo(dsUint32_t dsmHandle) {
|
||||
dsInt16_t rc=0;
|
||||
optStruct dsmOpt;
|
||||
ApiSessInfo dsmSessInfo;
|
||||
char t[50];
|
||||
|
||||
memset(&dsmOpt,0x00,sizeof(dsmOpt));
|
||||
rc = dsmQuerySessOptions(dsmHandle, &dsmOpt);
|
||||
|
||||
if (rc)
|
||||
printf("dsmQuerySessOptions error on issueing Query Session Options. Rc = %d\n",rc);
|
||||
else {
|
||||
printf("dsmQuerySessOptions:\n");
|
||||
printf(" DSMI_DIR: %s\n",dsmOpt.dsmiDir);
|
||||
printf(" DSMI_CONFIG: %s\n",dsmOpt.dsmiConfig);
|
||||
printf(" SErvername: %s\n",dsmOpt.serverName);
|
||||
printf(" COMMmethod: %d\n",dsmOpt.commMethod);
|
||||
printf(" TCPServerAddress: %s\n",dsmOpt.serverAddress);
|
||||
printf(" NODEName: %s\n",dsmOpt.nodeName);
|
||||
printf(" COMPRESSIon: %d\n",dsmOpt.compression);
|
||||
printf(" COMPRESSAlways: %d\n",dsmOpt.compressalways);
|
||||
printf(" PASSWORDAccess: %d\n",dsmOpt.passwordAccess);
|
||||
}
|
||||
|
||||
memset(&dsmSessInfo,0x00,sizeof(ApiSessInfo));
|
||||
dsmSessInfo.stVersion = ApiSessInfoVersion; /* Init struct version */
|
||||
rc = dsmQuerySessInfo(dsmHandle, &dsmSessInfo);
|
||||
|
||||
if (rc)
|
||||
printf("dsmQuerySessOptions error on issueing Query Session Options. Rc = %d\n",rc);
|
||||
else {
|
||||
printf("\n");
|
||||
printf("dsmQuerySessInfo:\n");
|
||||
printf(" Server Information:\n");
|
||||
printf(" Name: %s\n",dsmSessInfo.adsmServerName);
|
||||
printf(" Host: %s\n",dsmSessInfo.serverHost);
|
||||
printf(" Port: %u\n",dsmSessInfo.serverPort);
|
||||
printf(" Date: %s\n",dsmDateToStr(dsmSessInfo.serverDate));
|
||||
printf(" Type: %s\n",dsmSessInfo.serverType);
|
||||
printf(" Version: %i.%i.%i.%i\n",
|
||||
dsmSessInfo.serverVer,
|
||||
dsmSessInfo.serverRel,
|
||||
dsmSessInfo.serverLev,
|
||||
dsmSessInfo.serverSubLev);
|
||||
printf(" Archive Retention Protection : %s\n",dsmSessInfo.archiveRetentionProtection ? "YES" : "NO");
|
||||
printf("\n");
|
||||
printf(" Client Information:\n");
|
||||
printf(" Node: %s\n",dsmSessInfo.id);
|
||||
printf(" Node Type: %s\n",dsmSessInfo.nodeType);
|
||||
printf(" Filespace delimiter: %c\n",dsmSessInfo.fsdelim);
|
||||
printf(" 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"); break;
|
||||
default : strcpy(t,"UNKNOWN");
|
||||
}
|
||||
printf(" Client compression: %s\n",t);
|
||||
|
||||
switch (dsmSessInfo.archDel) {
|
||||
case ARCHDEL_YES : strcpy(t,"YES"); break;
|
||||
case ARCHDEL_NO : strcpy(t,"NO"); break;
|
||||
default : strcpy(t,"UNKNOWN");
|
||||
}
|
||||
printf(" ARCHIVE Delete: %s\n",t);
|
||||
|
||||
switch (dsmSessInfo.backDel) {
|
||||
case BACKDEL_YES : strcpy(t,"YES"); break;
|
||||
case ARCHDEL_NO : strcpy(t,"NO"); break;
|
||||
default : strcpy(t,"UNKNOWN");
|
||||
}
|
||||
printf(" BACKUP delete: %s\n",t);
|
||||
|
||||
printf(" MAX objects per transactions: %u\n", dsmSessInfo.maxObjPerTxn);
|
||||
printf(" LAN FREE Enabled: %s\n",dsmSessInfo.lanFreeEnabled ? "YES" : "NO");
|
||||
printf(" Deduplication: %s\n",dsmSessInfo.dedupType == dedupClientOrServer ? "Client Or Server" : "Server Only");
|
||||
printf("\n");
|
||||
printf(" General session info:\n");
|
||||
printf(" Owner: %s\n",dsmSessInfo.owner);
|
||||
printf(" API Config file: %s\n",dsmSessInfo.confFile);
|
||||
printf("\n");
|
||||
printf(" Policy Information:\n");
|
||||
printf(" Domain name: %s\n",dsmSessInfo.domainName);
|
||||
printf(" Policyset name: %s\n",dsmSessInfo.policySetName);
|
||||
printf(" Policy activation date: %s\n",dsmDateToStr(dsmSessInfo.polActDate));
|
||||
printf(" Default management class: %s\n",dsmSessInfo.dfltMCName);
|
||||
printf(" BACKUP retention grace: %u days\n",dsmSessInfo.gpBackRetn);
|
||||
printf(" ARCHIVE retention grace: %u days\n",dsmSessInfo.gpArchRetn);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Query TSM for a list of objects.
|
||||
*
|
||||
* We use a callback to process the list, the callback should return:
|
||||
* -1 upon error condition, application should exit.
|
||||
* 0 if tsm_queryfile() should skip processing the remaining matches.
|
||||
* 1 otherwise.
|
||||
*/
|
||||
dsInt16_t tsm_queryfile(dsUint32_t dsmHandle, dsmObjName *objName, char *description, dsmSendType sendtype, char verbose, tsm_query_callback usercb, void * userdata, char *pitdate, int querytype) {
|
||||
dsInt16_t rc=0;
|
||||
DataBlk qResp;
|
||||
dsmQueryType qType;
|
||||
qryArchiveData qaData;
|
||||
qryRespArchiveData qaResp;
|
||||
qryBackupData qbData;
|
||||
qryRespBackupData qbResp;
|
||||
dsmQueryBuff *qDataP;
|
||||
|
||||
if (verbose)
|
||||
fprintf(stderr,"tsm_queryfile: Query filespace %s\n",dsmObjnameToStr(*objName));
|
||||
|
||||
memset(&qResp,0x00,sizeof(DataBlk));
|
||||
qResp.stVersion = DataBlkVersion;
|
||||
|
||||
if (sendtype == stArchiveMountWait || sendtype == stArchive) {
|
||||
qType = qtArchive;
|
||||
|
||||
memset(&qaData,0x00,sizeof(qryArchiveData));
|
||||
qaData.stVersion = qryArchiveDataVersion;
|
||||
qaData.objName = objName;
|
||||
qaData.owner = "";
|
||||
qaData.insDateLowerBound.year = DATE_MINUS_INFINITE;
|
||||
qaData.insDateUpperBound.year = DATE_PLUS_INFINITE;
|
||||
qaData.expDateLowerBound.year = DATE_MINUS_INFINITE;
|
||||
qaData.expDateUpperBound.year = DATE_PLUS_INFINITE;
|
||||
qaData.descr = description ? description : "*";
|
||||
|
||||
qDataP = &qaData;
|
||||
|
||||
qaResp.stVersion = qryRespArchiveDataVersion;
|
||||
|
||||
qResp.bufferPtr = (char *) &qaResp;
|
||||
qResp.bufferLen = sizeof(qaResp);
|
||||
|
||||
} else {
|
||||
qType = qtBackup;
|
||||
|
||||
memset(&qbData,0x00,sizeof(qryBackupData));
|
||||
qbData.stVersion = qryBackupDataVersion;
|
||||
qbData.objName = objName;
|
||||
qbData.owner = "";
|
||||
qbData.objState = querytype;
|
||||
|
||||
if (pitdate) {
|
||||
qbData.pitDate = dsmStrToDate(pitdate,verbose);
|
||||
} else {
|
||||
qbData.pitDate.year = DATE_MINUS_INFINITE;
|
||||
}
|
||||
|
||||
qDataP = &qbData;
|
||||
|
||||
qbResp.stVersion = qryRespBackupDataVersion;
|
||||
|
||||
qResp.bufferPtr = (char *) &qbResp;
|
||||
qResp.bufferLen = sizeof(qbResp);
|
||||
}
|
||||
|
||||
rc = dsmBeginQuery(dsmHandle, qType, qDataP);
|
||||
if (rc != DSM_RC_OK) {
|
||||
tsm_printerr(dsmHandle,rc,"tsm_queryfile: dsmBeginQuery failed");
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Loop and apply our callback to the result */
|
||||
while ((rc = dsmGetNextQObj(dsmHandle, &qResp)) == DSM_RC_MORE_DATA) {
|
||||
int cbret;
|
||||
|
||||
if(verbose > 1) {
|
||||
dsmObjName *rObjName;
|
||||
|
||||
if(qType == qtArchive) {
|
||||
qryRespArchiveData *qr = (void *) qResp.bufferPtr;
|
||||
rObjName = &(qr->objName);
|
||||
|
||||
} else if(qType == qtBackup) {
|
||||
qryRespBackupData *qr = (void *) qResp.bufferPtr;
|
||||
rObjName = &(qr->objName);
|
||||
|
||||
} else {
|
||||
fprintf(stderr,"tsm_queryfile: Internal error: Unknown qType %d\n",qType);
|
||||
|
||||
return DSM_RC_UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
fprintf(stderr,"tsm_queryfile: Match file %s\n",dsmObjnameToStr(*rObjName));
|
||||
}
|
||||
|
||||
if (usercb == NULL)
|
||||
continue;
|
||||
|
||||
cbret = usercb(qType,&qResp,userdata);
|
||||
if (cbret < 0) {
|
||||
return DSM_RC_UNKNOWN_ERROR;
|
||||
|
||||
} else if(cbret == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (rc != DSM_RC_FINISHED && rc != DSM_RC_MORE_DATA) {
|
||||
tsm_printerr(dsmHandle, rc, "tsm_queryfile: dsmGetNextObj failed");
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = dsmEndQuery(dsmHandle);
|
||||
if (rc != DSM_RC_OK) {
|
||||
tsm_printerr(dsmHandle,rc,"tsm_queryfile: dsmEndQuery failed");
|
||||
return rc;
|
||||
}
|
||||
|
||||
return DSM_RC_OK;
|
||||
}
|
Reference in New Issue
Block a user