📄 mt.c
字号:
}
for(count=0;driveh[count].bit!=0;count++) {
prnfeat(driveh[count].txt,driveh[count].bit & driveparams.FeaturesHigh);
}
}
void closeh(HANDLE tapedrive) {
if (CloseHandle(tapedrive)==FALSE) error("closing tape handle");
}
void errorclose(char *txt, HANDLE tapedrive) {
error(txt);
closeh(tapedrive);
exit(1);
}
void preptape(HANDLE tapedrive, DWORD cmd, char *txt) {
if (PrepareTape(tapedrive,cmd,FALSE)!=NO_ERROR) {
errorclose(txt,tapedrive);
} else {
printf("%s completed OK\n", txt);
}
}
void doerase(HANDLE tapedrive, DWORD cmd, char *txt) {
if (EraseTape(tapedrive,cmd,TRUE)!=NO_ERROR) {
errorclose(txt,tapedrive);
} else {
printf("%s completed OK\n",txt);
}
}
DWORD64 GetNumber(char *txt) {
unsigned char unit=0; // number of bits to shift result
DWORD64 number=0;
unsigned char c;
for (c=0;(c<100) && (txt[c]!='\0');c++) {
switch (txt[c]) {
case 'k':
case 'K':
unit=10; // 1Kb in bits to shift
break;
case 'm':
case 'M':
unit=20; // 1Mb in bits to shift
break;
case 'G':
case 'g':
unit=30; // 1Gb in bits to shift
break;
}
if ((txt[c]<'0') || (txt[c]>'9')) txt[c]='\0';
}
sscanf(txt,"%I64d",&number);
return number<<unit;
}
#define getdword(a) ((DWORD) (GetNumber(a) & 0xffffffff)) // tisk
DWORD getdeviceblocksize(HANDLE tapedrive) {
TAPE_GET_DRIVE_PARAMETERS driveparams;
DWORD junk;
junk =sizeof(TAPE_GET_DRIVE_PARAMETERS);
if (GetTapeParameters(tapedrive,GET_TAPE_DRIVE_INFORMATION,&junk,&driveparams)!=NO_ERROR) {
errorclose("getting tape drive information (block size)",tapedrive);
} else { // warn about block size under 1KB or over 1Mb
if ((driveparams.DefaultBlockSize<1024) || (driveparams.DefaultBlockSize>1048576)) {
printf("Warning: Drive reports block size as %d bytes\n",driveparams.DefaultBlockSize);
}
return driveparams.DefaultBlockSize;
}
}
DWORD getmediablocksize(HANDLE tapedrive) {
TAPE_GET_MEDIA_PARAMETERS mediaparams;
DWORD junk;
junk =sizeof(TAPE_GET_MEDIA_PARAMETERS);
if (GetTapeParameters(tapedrive,GET_TAPE_MEDIA_INFORMATION,&junk,&mediaparams)!=NO_ERROR) {
errorclose("getting tape drive information (block size)",tapedrive);
} else {
return mediaparams.BlockSize;
}
}
void setmediablocksize(HANDLE tapedrive, DWORD blocks) {
TAPE_SET_MEDIA_PARAMETERS mediaparams;
mediaparams.BlockSize = blocks;
if (SetTapeParameters(tapedrive,SET_TAPE_MEDIA_INFORMATION,&mediaparams)!=NO_ERROR) {
printf("Use drivestatus to check the block size (%u) is supported by the drive\n",blocks);
errorclose("setting block size",tapedrive);
}
}
void printtapeposition(HANDLE tapedrive) {
DWORD part, posl, posh;
DWORD64 bytePosition;
if (GetTapePosition(tapedrive,TAPE_ABSOLUTE_POSITION,&part, &posl, &posh)!=NO_ERROR) {
errorclose("getting tape position",tapedrive);
} else {
printf("Current Partition\t: %u\n",part);
printf("Absolute Block Position\t: 0x%.8x 0x%.8x (%d %d)\n",posh, posl,posh, posl);
bytePosition=(((DWORD64)posh<<32)+posl)*getdeviceblocksize(tapedrive);
printf("Absolute Byte Position\t: 0x%.16I64x\n",bytePosition);
}
if (GetTapeStatus(tapedrive)!=NO_ERROR) {
errorclose("getting tape status", tapedrive);
} else {
printf("Status\t\t\t: Ready\n");
}
}
BOOL variableblocks(HANDLE tapedrive) {
TAPE_GET_DRIVE_PARAMETERS driveparams;
DWORD junk;
junk =sizeof(TAPE_GET_DRIVE_PARAMETERS);
if (GetTapeParameters(tapedrive,GET_TAPE_DRIVE_INFORMATION,&junk,&driveparams)!=NO_ERROR) {
errorclose("getting drive information (variable block support)",tapedrive);
} else {
return (driveparams.FeaturesLow & TAPE_DRIVE_VARIABLE_BLOCK);
}
}
void readtape(HANDLE tapedrive, char *filename, char *length) {
LPVOID buff;
HANDLE outf;
DWORD bytesread;
DWORD byteswritten;
DWORD result;
DWORD readbuffersize;
DWORD64 toread;
DWORD64 total=0;
if (variableblocks(tapedrive)) { // v0.16
readbuffersize=VARIABLE_BUFFER_LENGTH;
setmediablocksize(tapedrive,0);
} else {
readbuffersize=getmediablocksize(tapedrive); // v0.15 media not device block size
}
if (length[0]=='\0') {
toread=-1; // setting an unsigned to -1?
} else {
toread=GetNumber(length);
}
printtapeposition(tapedrive);
buff=VirtualAlloc(NULL,readbuffersize,MEM_COMMIT,PAGE_READWRITE);
if (buff==NULL) errorclose("allocating buffer",tapedrive);
outf = CreateFile(filename,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
if (outf==INVALID_HANDLE_VALUE) errorclose("opening output file",tapedrive);
result = ReadFile(tapedrive,buff,readbuffersize,&bytesread,NULL);
while ((bytesread>0) && (result!=0) && ((toread==-1) || (total<toread))) {
total+=bytesread;
printf("Bytes read: %I64d\r",total);
if (WriteFile(outf,buff,bytesread,&byteswritten,NULL)==0) {
closeh(outf);
errorclose("writing file",tapedrive);
}
result = ReadFile(tapedrive,buff,readbuffersize,&bytesread,NULL);
}
closeh(outf);
if (result==0) errorclose("reading tape",tapedrive);
printf("Read %I64d bytes (rounded up to nearest %d byte block)\n",total,readbuffersize);
printtapeposition(tapedrive);
}
int main(int argc, char **argv) {
char filename[512]="//./";
HANDLE tapedrive;
TAPE_GET_DRIVE_PARAMETERS driveparams;
TAPE_GET_MEDIA_PARAMETERS mediaparameters;
DWORD junk;
int command=DO_ENDLIST;
DWORD64 position;
int count;
int p1;
if (argc<2) usage();
if ((argc>2) && (strncasecmp(argv[2],"tape",4)==0)) {
strncat(filename,argv[2],500);
p1=3;
} else {
strncat(filename,"tape0",200);
p1=2;
}
for (count=0; opts[count].bit!=0; count++) {
if ((strcasecmp(argv[1],opts[count].txt)==0) && (argc==p1+opts[count].params)) {
command=opts[count].bit;
break;
}
}
if ((command==DO_ENDLIST) || (command==DO_USAGE)) usage();
tapedrive=CreateFile(filename,GENERIC_READ | GENERIC_WRITE,0,0,OPEN_EXISTING,0,NULL);
if (tapedrive==INVALID_HANDLE_VALUE) {
error("opening tape drive");
exit(1);
}
switch(command) {
case DO_LONGERASE:
doerase(tapedrive,TAPE_ERASE_LONG,"long erase");
break;
case DO_SHORTERASE:
doerase(tapedrive,TAPE_ERASE_SHORT,"short erase");
break;
case DO_FORMAT:
preptape(tapedrive,TAPE_FORMAT,"formatting. Try longerase for non QIC117 tape drives");
break;
case DO_LOAD:
preptape(tapedrive,TAPE_LOAD,"loading");
break;
case DO_LOCK:
preptape(tapedrive,TAPE_LOCK,"locking");
break;
case DO_TENSION:
preptape(tapedrive,TAPE_TENSION,"retensioning");
break;
case DO_UNLOAD:
preptape(tapedrive,TAPE_UNLOAD,"unloading");
break;
case DO_UNLOCK:
preptape(tapedrive,TAPE_UNLOCK,"unlocking");
break;
case DO_FIXEDPARTITION:
if (CreateTapePartition(tapedrive,TAPE_FIXED_PARTITIONS,0,0)!=NO_ERROR) {
errorclose("fixed partitioning",tapedrive);
} else {
printf("Partitioned OK\n");
}
break;
case DO_INITPARTITION:
if (CreateTapePartition(tapedrive,TAPE_INITIATOR_PARTITIONS,getdword(argv[p1]),getdword(argv[p1+1]))!=NO_ERROR) {
errorclose("initiator partitioning",tapedrive);
} else {
printf("Partitioned OK\n");
}
break;
case DO_PARTITION:
if (CreateTapePartition(tapedrive,TAPE_SELECT_PARTITIONS,getdword(argv[p1]),0)!=NO_ERROR) {
errorclose("select partitioning",tapedrive);
} else {
printf("Partitioned OK\n");
}
break;
case DO_REWIND:
if (SetTapePosition(tapedrive,TAPE_REWIND,0,0,0,TRUE)!=NO_ERROR) {
errorclose("rewinding",tapedrive);
} else {
printtapeposition(tapedrive);
}
break;
case DO_DRIVESTATUS:
junk =sizeof(TAPE_GET_DRIVE_PARAMETERS);
if (GetTapeParameters(tapedrive,GET_TAPE_DRIVE_INFORMATION,&junk,&driveparams)!=NO_ERROR) {
errorclose("getting tape drive information",tapedrive);
} else {
printdriveparams(driveparams);
}
break;
case DO_MEDIASTATUS:
junk =sizeof(TAPE_GET_MEDIA_PARAMETERS);
if (GetTapeParameters(tapedrive,GET_TAPE_MEDIA_INFORMATION,&junk,&mediaparameters)!=NO_ERROR) {
errorclose("getting media information",tapedrive);
} else {
printmediaparams(mediaparameters);
printtapeposition(tapedrive);
}
break;
case DO_SEEK:
case DO_BYTESEEK:
position = GetNumber(argv[p1]);
if (command==DO_BYTESEEK) position=position/getdeviceblocksize(tapedrive);
if (SetTapePosition(tapedrive,TAPE_ABSOLUTE_BLOCK,0,(DWORD) (position & 0xffffffff),(DWORD) ((position>>32) & 0xffffffff),FALSE)!=NO_ERROR) {
errorclose("setting position",tapedrive);
} else {
printtapeposition(tapedrive);
}
break;
case DO_READ:
readtape(tapedrive,argv[p1],"");
break;
case DO_LICENCE:
printf("%s",licencetext);
break;
case DO_READPART:
readtape(tapedrive,argv[p1],argv[p1+1]);
break;
case DO_BLOCK:
setmediablocksize(tapedrive,GetNumber(argv[p1]));
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -