diff --git a/lib/dsmlist.c b/lib/dsmlist.c index 93bfc80..a2a66d4 100644 --- a/lib/dsmlist.c +++ b/lib/dsmlist.c @@ -12,14 +12,50 @@ dsBool_t headerPrinted=bFalse; // Have we rendered the heading row yet +char *units(double size) { + extern int verbose; + static const char *SIZES[] = { "B", "KiB", "MiB", "GiB" }; + int div = 0; + double rem = 0; + int base = 1024; + + char *s; + + s = "\0"; + s = malloc(128); + if (s==NULL) { + perror("Arg, out of memory?"); + exit(255); + } + memset(s,0x00,(sizeof s)); + + while (size >= base && div < (int)(sizeof SIZES / sizeof *SIZES)-1) { + if (verbose > 2) + fprintf(stderr,"BEFORE: %s: SIZE: [%3.2f], DIV: [%d], REM: [%3.2f]\n",__func__,size,div,rem); + + rem = ((int)size % base); + size /= base; + div++; + } + + if (verbose > 2) + fprintf(stderr,"AFTER: %s: SIZE: [%3.2f], DIV: [%d], REM: [%3.2f]\n",__func__,size,div,rem); + + sprintf(s,"%3.2f %s",size,SIZES[div]); + + return s; +} + /* * Our Callback to show what is in TSM */ -int tsm_listfile_cb(dsmQueryType qType, DataBlk *qResp, void *userdata) { +int tsm_listfile_cb(dsmQueryType qType, DataBlk *qResp, void *userdata, dsBool_t friendly) { char stor[2]; char state[3]; char ced[4]; char objInfo[DSM_MAX_OBJINFO_LENGTH]; + char *s; + s = malloc(1024); if (userdata != NULL ) { debugLog(0,__func__,"ERROR: Internal error: userdata != NULL",0); @@ -28,12 +64,12 @@ int tsm_listfile_cb(dsmQueryType qType, DataBlk *qResp, void *userdata) { if (qType == qtArchive) { if (! headerPrinted++) { - printf("%40s %2s %s %3s %19s %19s %10s %10s %10s", + printf("%-40s %2s %s %3s %-19s %-19s %12s %-10s %-10s", "NAME", "ST", "L", "CED", - "BACKUP", + "ARCHIVE", "EXPIRE", "SIZE", "ID", @@ -74,12 +110,18 @@ int tsm_listfile_cb(dsmQueryType qType, DataBlk *qResp, void *userdata) { strcat(ced,respArchive.clientDeduplicated ? "D" : "-"); + if (friendly) { + s = units((double)dsmSizeToNum(respArchive.sizeEstimate,bFalse)); + } else { + sprintf(s,"%7.3f MB",dsmSizeToNum(respArchive.sizeEstimate,bTrue)); + } + // The Object Status - printf("%40s|%2s|%s|%3s|%19s|%19s|%7.3f MB|%u-%u|%s",dsmObjnameToStr(respArchive.objName),state,stor,ced,dsmDateToStr(respArchive.insDate),respArchive.expDate.year ? dsmDateToStr(respArchive.expDate) : "",dsmSizeToNum(respArchive.sizeEstimate,bTrue),respArchive.objId.hi,respArchive.objId.lo,respArchive.descr); + printf("%-40s|%2s|%s|%3s|%-19s|%-19s|%12s|%u-%8u|%10s",dsmObjnameToStr(respArchive.objName),state,stor,ced,dsmDateToStr(respArchive.insDate),respArchive.expDate.year ? dsmDateToStr(respArchive.expDate) : "",s,respArchive.objId.hi,respArchive.objId.lo,respArchive.descr); } else if (qType == qtBackup) { if (! headerPrinted++) { - printf("%40s %2s %s %3s %19s %19s %10s %10s", + printf("%-40s %2s %s %3s %-19s %-19s %12s %-10s", "NAME", "ST", "L", @@ -139,7 +181,13 @@ int tsm_listfile_cb(dsmQueryType qType, DataBlk *qResp, void *userdata) { strncat(objInfo,respBackup.objInfo,respBackup.objInfolen); #endif - printf("%40s|%2s|%s|%3s|%19s|%19s|%7.3f MB|%u-%8u",dsmObjnameToStr(respBackup.objName),state,stor,ced,dsmDateToStr(respBackup.insDate),respBackup.expDate.year ? dsmDateToStr(respBackup.expDate) : "",dsmSizeToNum(respBackup.sizeEstimate,bTrue),respBackup.objId.hi,respBackup.objId.lo); + if (friendly) { + s = units((double)dsmSizeToNum(respBackup.sizeEstimate,bFalse)); + } else { + sprintf(s,"%7.3f MB",dsmSizeToNum(respBackup.sizeEstimate,bTrue)); + } + + printf("%-40s|%2s|%s|%3s|%19s|%19s|%12s|%u-%8u",dsmObjnameToStr(respBackup.objName),state,stor,ced,dsmDateToStr(respBackup.insDate),respBackup.expDate.year ? dsmDateToStr(respBackup.expDate) : "",s,respBackup.objId.hi,respBackup.objId.lo); } else { fprintf(stderr,"%s: UNKNOWN Type %d\n",__func__,qType); return -1; @@ -156,10 +204,10 @@ int tsm_listfile_cb(dsmQueryType qType, DataBlk *qResp, void *userdata) { /* * List objects that are in TSM */ -int tsm_listfile(dsUint32_t sesshandle, dsmQueryType qType, qryArchiveData qaData, qryBackupData qbData) { +int tsm_listfile(dsUint32_t sesshandle, dsmQueryType qType, qryArchiveData qaData, qryBackupData qbData, dsBool_t friendly) { dsInt16_t rc=0; - rc = tsm_queryfile(sesshandle,qType,tsm_listfile_cb,NULL,qaData,qbData); + rc = tsm_queryfile(sesshandle,qType,tsm_listfile_cb,NULL,qaData,qbData,friendly); if (rc != DSM_RC_OK && rc != DSM_RC_ABORT_NO_MATCH) return 0; diff --git a/lib/dsmsendrecv.c b/lib/dsmsendrecv.c index 69a94df..4b22620 100644 --- a/lib/dsmsendrecv.c +++ b/lib/dsmsendrecv.c @@ -16,9 +16,12 @@ #include "../tsmpipe.h" -int tsm_matchone_cb(dsmQueryType qType, DataBlk *qResp, void *userdata) { +int tsm_matchone_cb(dsmQueryType qType, DataBlk *qResp, void *userdata, dsmBool_t friendly) { struct matchone_cb_data *cbdata = userdata; + if (friendly) + debugLog(0,__func__,"ERROR: Friendly is set?",1); + cbdata->numfound++; if (qType == qtArchive) { @@ -339,6 +342,7 @@ int tsm_restorefile(dsUint32_t dsmHandle, dsmQueryType qType, qryArchiveData qaD dsmGetList getList; DataBlk dataBlk; dsmGetType gType; + dsmBool_t friendly=bFalse; memset(&cbdata,0x00,sizeof(cbdata)); cbdata.numfound = 0; @@ -348,14 +352,14 @@ int tsm_restorefile(dsUint32_t dsmHandle, dsmQueryType qType, qryArchiveData qaD fprintf(stderr,"%s: Starting to receive %s via stdin\n",__func__,dsmObjnameToStr(*qaData.objName)); gType = gtArchive; - rc = tsm_queryfile(dsmHandle,qType,tsm_matchone_cb,&cbdata,qaData,qbData); + rc = tsm_queryfile(dsmHandle,qType,tsm_matchone_cb,&cbdata,qaData,qbData,friendly); } else if (qType == qtBackup) { if (verbose) fprintf(stderr,"%s: Starting to receive %s via stdin\n",__func__,dsmObjnameToStr(*qbData.objName)); gType = gtBackup; - rc = tsm_queryfile(dsmHandle,qType,tsm_matchone_cb,&cbdata,qaData,qbData); + rc = tsm_queryfile(dsmHandle,qType,tsm_matchone_cb,&cbdata,qaData,qbData,friendly); } else { fprintf(stderr,"%s: UNKNOWN Type %d\n",__func__,qType); @@ -438,10 +442,11 @@ int tsm_deletefile(dsUint32_t dsmHandle, dsmQueryType qType, qryArchiveData qaDa dsmDelInfo *dInfoP; dsmDelType dType; struct matchone_cb_data cbdata; + dsmBool_t friendly=bFalse; cbdata.numfound = 0; - rc = tsm_queryfile(dsmHandle,qType,tsm_matchone_cb,&cbdata,qaData,qbData); + rc = tsm_queryfile(dsmHandle,qType,tsm_matchone_cb,&cbdata,qaData,qbData,friendly); if (rc != DSM_RC_OK) { return 0; } diff --git a/lib/dsmsession.c b/lib/dsmsession.c index d7b6893..bd695cc 100644 --- a/lib/dsmsession.c +++ b/lib/dsmsession.c @@ -197,7 +197,7 @@ int tsm_sessioninfo(dsUint32_t dsmHandle) { case DSM_COMM_TCP : strcpy(t,"TCP/IP"); break; case DSM_COMM_NAMEDPIPE : strcpy(t,"NAMED PIPE"); break; case DSM_COMM_SHM : strcpy(t,"SHARED MEMORY"); break; - case 6 : strcpy(t,"TCP/IP v6"); break; // There is no DSM_COMM_ const for TCPIPv6 + case DSM_COMM_TCPIP6 : strcpy(t,"TCP/IP v6"); break; default: strcpy(t,"UNKNOWN"); } @@ -293,7 +293,7 @@ int tsm_sessioninfo(dsUint32_t dsmHandle) { * 0 if tsm_queryfile() should skip processing the remaining matches. * 1 otherwise. */ -dsInt16_t tsm_queryfile(dsUint32_t dsmHandle, dsmQueryType qType, tsm_query_callback usercb, void *userdata, qryArchiveData qaData, qryBackupData qbData) { +dsInt16_t tsm_queryfile(dsUint32_t dsmHandle, dsmQueryType qType, tsm_query_callback usercb, void *userdata, qryArchiveData qaData, qryBackupData qbData, dsBool_t friendly) { extern int verbose; dsInt16_t rc=0; dsmQueryBuff *qDataP; @@ -371,7 +371,7 @@ dsInt16_t tsm_queryfile(dsUint32_t dsmHandle, dsmQueryType qType, tsm_query_call if (usercb == NULL) continue; - cbret = usercb(qType,&qResp,userdata); + cbret = usercb(qType,&qResp,userdata,friendly); if (cbret < 0) { return DSM_RC_UNKNOWN_ERROR; diff --git a/tsmpipe.c b/tsmpipe.c index a14aa92..fa20c66 100644 --- a/tsmpipe.c +++ b/tsmpipe.c @@ -83,6 +83,7 @@ void usage(void) { " -s and -f are required arguments for (-A/ -B operations):\n" " -s fsname Name of filespace in TSM\n" " -f filepath Path to file within filesystem in TSM\n" + " -F Friendly output, only valid for -t\n" " -l length Length of object to store. If guesstimating, too large\n" " is better than too small\n" " -L length Length of object to store. But also update the FS with\n" @@ -116,6 +117,7 @@ int main(int argc, char *argv[]) { int action=0; char *space=NULL, *filename=NULL, *lenstr=NULL, *desc=NULL, *pitdate=NULL, *options=NULL, *expdate_low=NULL, *expdate_high=NULL, *insdate_low=NULL, *insdate_high=NULL; dsBool_t summary=bFalse; + dsBool_t friendly=bFalse; off_t length; dsUint32_t dsmHandle; dsmQueryType qType=0xff; // We set this to an unlikely value, it should be set correctly via our getopt @@ -128,7 +130,7 @@ int main(int argc, char *argv[]) { char *digest=NULL; #endif - while ((c = getopt(argc, argv, "hiABcxdtUvVe:E:f:l:L:m:n:N:s:D:O:P:")) != -1) { + while ((c = getopt(argc, argv, "hiABcxdtUvVe:E:f:Fl:L:m:n:N:s:D:O:P:")) != -1) { switch(c) { case 'h': usage(); break; case 'A': qType = qtArchive; break; @@ -145,6 +147,7 @@ int main(int argc, char *argv[]) { case 'V': summary = bTrue; break; case 's': space = optarg; break; case 'f': filename = optarg; break; + case 'F': friendly = bTrue; break; case 'l': lenstr = optarg; break; case 'L': lenstr = optarg; if (action != ACTION_CREATE) usage_action(); action = ACTION_CREATE_UPDATE; break; case 'D': desc = optarg; break; @@ -174,6 +177,10 @@ int main(int argc, char *argv[]) { debugLog(0,__func__,"ERROR: Must give one of -i, -c, -x, -d, -t",1); } + if (action != ACTION_LIST && friendly) { + debugLog(0,__func__,"ERROR: -F can only be used with -t",1); + } + if (pitdate && qType != qtBackup) { debugLog(0,__func__,"ERROR: -P can only be used with -B",1); } @@ -330,7 +337,7 @@ int main(int argc, char *argv[]) { case ACTION_LIST: debugLog(2,__func__,"LIST Operation",0); - rc = tsm_listfile(dsmHandle,qType,qaData,qbData); + rc = tsm_listfile(dsmHandle,qType,qaData,qbData,friendly); break; default: diff --git a/tsmpipe.h b/tsmpipe.h index 756e553..46c4936 100644 --- a/tsmpipe.h +++ b/tsmpipe.h @@ -1,4 +1,4 @@ -#define _TSMPIPE_VERSION "1.6.3" +#define _TSMPIPE_VERSION "1.6.4" #define ACTION_INFO 1 #define ACTION_CREATE 2 @@ -7,6 +7,7 @@ #define ACTION_LIST 5 #define ACTION_UPDATE 6 #define ACTION_CREATE_UPDATE 7 +#define DSM_COMM_TCPIP6 6 // There is no DSM_COMM_ const for TCPIPv6 // If you want to use MD5/SHA1 calculations as the data goes in here, ensure this is defined. #define USE_DIGEST @@ -15,7 +16,7 @@ #include #endif -typedef int (*tsm_query_callback)(dsmQueryType, DataBlk *, void *); +typedef int (*tsm_query_callback)(dsmQueryType, DataBlk *, void *, dsmBool_t friendly); struct matchone_cb_data { int numfound; dsStruct64_t objId; dsUint32_t copyGroup; }; @@ -24,12 +25,12 @@ extern void debugLog (int level, const char *func, char *message, int die); extern dsmDate dsmStrToDate(char *s); extern dsmObjName dsmNameToObjname(char *fsname, char *filename); -extern dsInt16_t tsm_queryfile(dsUint32_t sesshandle, dsmQueryType qType, tsm_query_callback usercb, void *userdata, qryArchiveData qaData, qryBackupData qbData); +extern dsInt16_t tsm_queryfile(dsUint32_t sesshandle, dsmQueryType qType, tsm_query_callback usercb, void *userdata, qryArchiveData qaData, qryBackupData qbData, dsBool_t friendly); extern dsUint32_t tsm_initsess(char *options); extern dsBool_t compressEnabled; extern int tsm_deletefile (dsUint32_t dsmHandle, dsmQueryType qType, qryArchiveData qaData, qryBackupData qbData); -extern int tsm_listfile (dsUint32_t dsmHandle, dsmQueryType qType, qryArchiveData qaData, qryBackupData qbData); +extern int tsm_listfile (dsUint32_t dsmHandle, dsmQueryType qType, qryArchiveData qaData, qryBackupData qbData, dsBool_t friendly); extern int tsm_restorefile(dsUint32_t dsmHandle, dsmQueryType qType, qryArchiveData qaData, qryBackupData qbData); #ifdef USE_DIGEST extern double tsm_sendfile (dsUint32_t dsmHandle, char *fsname, char *filename, long long length, char *description, dsmSendType sendtype, dsBool_t startstop, dsBool_t summary, char *digest);