mirror of
https://github.com/prirun/p50em.git
synced 2026-01-11 23:42:56 +00:00
146 lines
3.4 KiB
C
146 lines
3.4 KiB
C
/* mtwrite.c, Jim Wilcoxson, July 14, 2011
|
|
Writes a .TAP disk file to a magtape
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <fcntl.h>
|
|
#include <sys/mtio.h>
|
|
|
|
#define BUFSIZE 20000
|
|
|
|
/* in the tap format, record lengths are always stored little-endian */
|
|
|
|
int readint_le () {
|
|
int n,ch;
|
|
|
|
n = getchar() | getchar()<<8 | getchar()<<16 | getchar()<<24;
|
|
if (feof(stdin)) {
|
|
fprintf(stderr,"End of file reading record length, position = %d\n", ftell(stdin));
|
|
exit(0);
|
|
}
|
|
return n;
|
|
}
|
|
|
|
main (int argc, char **argv) {
|
|
|
|
char *infile;
|
|
int tapefd, fdin;
|
|
struct mtop mt_cmd;
|
|
struct mtget mt_status;
|
|
struct mtpos mt_pos;
|
|
int filenr, relrecnr;
|
|
int reclen, reclen2;
|
|
int n,n2;
|
|
int outpos;
|
|
int mark;
|
|
char buf[BUFSIZE];
|
|
|
|
filenr = 1;
|
|
relrecnr = 0;
|
|
mark = 0;
|
|
|
|
if ((tapefd=open("/dev/st0", O_RDWR)) == -1) {
|
|
perror("Error opening tape drive");
|
|
goto done;
|
|
}
|
|
|
|
/* set tape blocksize to 0 */
|
|
|
|
mt_cmd.mt_op = MTSETDRVBUFFER;
|
|
mt_cmd.mt_count = 0;
|
|
if (ioctl(tapefd, MTIOCTOP, &mt_cmd) != 0) {
|
|
perror("Error setting variable blocksize");
|
|
goto done;
|
|
}
|
|
|
|
/* set buffering */
|
|
|
|
mt_cmd.mt_op = MTSETDRVBUFFER;
|
|
mt_cmd.mt_count = 1;
|
|
if (ioctl(tapefd, MTIOCTOP, &mt_cmd) != 0) {
|
|
perror("Error setting buffering params");
|
|
goto done;
|
|
}
|
|
mt_cmd.mt_op = MTSETDRVBUFFER;
|
|
mt_cmd.mt_count = 1;
|
|
mt_cmd.mt_count |= MT_ST_BOOLEANS | MT_ST_BUFFER_WRITES | MT_ST_ASYNC_WRITES;
|
|
if (ioctl(tapefd, MTIOCTOP, &mt_cmd) != 0) {
|
|
perror("Error setting buffering params");
|
|
goto done;
|
|
}
|
|
|
|
#if 0
|
|
/* set density: 1=800bpi; 2=1600bpi; 3=6250bpi */
|
|
|
|
mt_cmd.mt_op = MTSETDENSITY;
|
|
mt_cmd.mt_count = 2;
|
|
if (ioctl(tapefd, MTIOCTOP, &mt_cmd) != 0) {
|
|
perror("Error setting variable blocksize");
|
|
goto done;
|
|
}
|
|
#endif
|
|
|
|
while(1) {
|
|
relrecnr++;
|
|
reclen = readint_le();
|
|
if (reclen == 0xFFFFFFFF) /* end of medium */
|
|
goto done;
|
|
else if (reclen & 0x80000000) { /* error in record */
|
|
printf("File %d, record %d contains error; writing zero record\n", filenr, relrecnr);
|
|
*(int *)buf = 0;
|
|
buf[0] = 4;
|
|
*(int *)(buf+4) = 0;
|
|
*(int *)(buf+8) = *(int *)buf;
|
|
if (write(tapefd, buf, 12) != 12) {
|
|
perror("Error writing error record");
|
|
goto done;
|
|
}
|
|
} else if (reclen == 0) {
|
|
printf("File mark %d\n", filenr);
|
|
mt_cmd.mt_op = MTWEOF;
|
|
mt_cmd.mt_count = 1;
|
|
if (ioctl(tapefd, MTIOCTOP, &mt_cmd) != 0) {
|
|
perror("Error writing tape mark");
|
|
goto done;
|
|
}
|
|
filenr++;
|
|
relrecnr = 0;
|
|
} else {
|
|
reclen = reclen & 0x00FFFFFF;
|
|
if (reclen > BUFSIZE) {
|
|
fprintf(stderr,"Record too big at record %d: increase BUFSIZE to %d\n", relrecnr, reclen);
|
|
exit(1);
|
|
}
|
|
n=fread(buf, 1, reclen, stdin);
|
|
if (n != reclen) {
|
|
fprintf(stderr,"Read error at record %d, expected %d, got %d bytes\n", relrecnr, reclen, n);
|
|
exit(1);
|
|
}
|
|
reclen2 = readint_le();
|
|
if (reclen2 != reclen) {
|
|
fprintf(stderr,"Read error at record %d, expected trailing reclen %d, got %d\n", relrecnr, reclen, reclen2);
|
|
exit(1);
|
|
}
|
|
if ((n2=write(tapefd, buf, reclen)) != reclen) {
|
|
if (n2 == -1) {
|
|
perror("Error writing tape device");
|
|
goto done;
|
|
}
|
|
printf("Error writing tape device, read %d, wrote %d\n", reclen, n2);
|
|
goto done;
|
|
}
|
|
}
|
|
}
|
|
|
|
done:
|
|
sleep(2);
|
|
mt_cmd.mt_op = MTREW;
|
|
mt_cmd.mt_count = 0;
|
|
if (ioctl(tapefd, MTIOCTOP, &mt_cmd) != 0) {
|
|
perror("Error rewinding");
|
|
}
|
|
close(tapefd);
|
|
exit(1);
|
|
}
|