aboutsummaryrefslogtreecommitdiff
path: root/unix/boot/bootlib/tape.c
blob: 6d949f72deeb1d2d3be1b339644f36437882ee4f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
 */

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>

#define	NOKNET
#define import_spp
#define import_finfo
#define import_knames
#include <iraf.h>

/*
 * TAPE.C -- Generalized binary file i/o to a tape drive or other devices.
 *
 *	fd = tape_open (fname, mode)
 *	    tape_close (fd)
 *	nb = tape_read (fd, buf, maxbytes)
 *     nb = tape_write (fd, buf, nbytes)
 *
 * Only one "tape" file can be open at a time (unless all open files are of
 * the same type).  Since we call ZZRDMT and ZZWRMT directly, only blocked
 * output is permitted (there is no internal buffering).  Only sequential
 * output is permitted to disk (there is no seek entry point).
 *
 * NOTE - For the IRAF V2.10 version of this utility, only host device names
 * are permitted.  The IRAF device names "mta", "mtb", etc are not supported
 * as the tapefile file is not read.
 */

#define	TF_STDIN	0
#define	TF_STDOUT	1
#define	TF_BINARY	2
#define	TF_TAPE		3

#define	R	0
#define	W	1
#define	RW	2

/* Tape position structure (V2.10). */
struct mtpos {
        int     filno;                  /* current file (1=first) */
        int     recno;                  /* current record (1=first) */
        int     nfiles;                 /* number of files on tape */
        int     tapeused;               /* total tape used (Kb) */
        int     pflags;                 /* i/o status bitflags (output) */
};

/* MTPOS bitflags. */
#define MF_ERR  0001    /* i/o error occurred in last operation */
#define MF_EOF  0002    /* a tape mark was seen in the last operation */
#define MF_EOT  0004    /* end of tape seen in the last operation */
#define MF_EOR  0010    /* a record advance occurred in the last operation */

static	int ftype;
static	XINT acmode;
static	int ateof;
static	XLONG offset = 0;

static  int os_mtname (char *fname, char *osdev);

extern  int ZZOPMT(), ZOPNBF(), ZCLSBF(), ZZCLMT();
extern  int ZARDBF(), ZAWTBF(), ZZRDMT(), ZZWTMT(), ZAWRBF(), ZZWRMT();



/* TAPE_OPEN -- Open the named file, which need not actually be a tape device.
 */
int
tape_open (
  char	*fname,		/* file or device to be opened	*/
  int	mode 		/* access mode			*/
)
{
	PKCHAR	osfn[SZ_PATHNAME+1];
	XINT	chan;
	extern  char *vfn2osfn();


	if (strcmp (fname, "stdin") == 0) {
	    ftype = TF_STDIN;
	    if (mode != R)
		chan = ERR;
	    else
		chan = 1;	/* arbitrary */

	} else if (strcmp (fname, "stdout") == 0) {
	    ftype = TF_STDOUT;
	    if (mode != W)
		chan = ERR;
	    else
		chan = 1;	/* arbitrary */

	} else if (os_mtname (fname, (char *)osfn)) {
	    /* Open a magtape device.  Only host device names are permitted.
	     * Try to open without moving the tape (newfile=0).
	     */
	    register int *op;
	    struct  mtpos devpos;
	    int     nwords = sizeof(devpos) / sizeof(int);
	    XINT    newfile = 0;
	    char    *tapecap = ":np";

	    for (op = (int *)&devpos;  --nwords >= 0;  )
		*op++ = 0;
	    ftype = TF_TAPE;
	    if (mode == R)
		acmode = READ_ONLY;
	    else
		acmode = WRITE_ONLY;

	    ZZOPMT (osfn, &acmode, (PKCHAR *)tapecap, (XINT *)&devpos, 
		&newfile, &chan);

	} else {
	    /* Open a binary disk file.
	     */
	    ftype = TF_BINARY;
	    offset = 1;

	    strcpy ((char *)osfn, vfn2osfn (fname, 0));
	    if (mode == R)
		acmode = READ_ONLY;
	    else if (mode == W)
		acmode = NEW_FILE;
	    else
		acmode = READ_WRITE;

	    ZOPNBF (osfn, &acmode, &chan);
	}

	ateof = 0;

	return (chan == XERR ? ERR : chan);
}


/* TAPE_CLOSE -- Close a file opened with tape_open.
 */
int
tape_close (int fd)
{
	struct	mtpos devpos;
	XINT	x_fd=fd, status;

	if (ftype == TF_BINARY)
	    ZCLSBF (&x_fd, &status);
	else if (ftype == TF_TAPE)
	    ZZCLMT (&x_fd, (XINT *)&devpos, &status);
	else
	    status = XOK;

	return (status == XERR ? ERR : OK);
}


/* TAPE_READ -- Read from a file opened with tape_open.
 */
int
tape_read (
  int	fd,			/* input file		*/
  char	*buf,			/* output buffer	*/
  int	maxbytes 		/* max bytes to read	*/
)
{
	struct	mtpos devpos;
	XINT	x_fd=fd, x_maxbytes=maxbytes, status;

	if (ateof)
	    return (0);

	if (ftype == TF_STDIN) {
	    status = read (0, buf, maxbytes);
	} else if (ftype == TF_BINARY) {
	    ZARDBF (&x_fd, (XCHAR *)buf, &x_maxbytes, &offset);
	    ZAWTBF (&x_fd, &status);
	    if (status > 0)
		offset += status;
	} else if (ftype == TF_TAPE){
	    ZZRDMT (&x_fd, (XCHAR *)buf, &x_maxbytes, &offset);
	    ZZWTMT (&x_fd, (XINT *)&devpos, &status);
	    if (devpos.pflags & MF_EOF)
		ateof++;
	} else
	    status = XERR;

	return (status == XERR ? ERR : status);
}


/* TAPE_WRITE -- Write to a file opened with tape_open.
 */
int
tape_write (
  int	fd,			/* output file		*/
  char	*buf,			/* input bufferr	*/
  int	nbytes 			/* nbytes to write	*/
)
{
	struct	mtpos devpos;
	XINT	x_fd=fd, x_nbytes=nbytes, status;

	if (ftype == TF_STDOUT) {
	    status = write (1, buf, nbytes);
	} else if (ftype == TF_BINARY) {
	    ZAWRBF (&x_fd, (XCHAR *)buf, &x_nbytes, &offset);
	    ZAWTBF (&x_fd, &status);
	    if (status > 0)
		offset += status;
	} else if (ftype == TF_TAPE) {
	    ZZWRMT (&x_fd, (XCHAR *)buf, &x_nbytes, &offset);
	    ZZWTMT (&x_fd, (XINT *)&devpos, &status);
	} else
	    status = XERR;

	return (status == XERR ? ERR : status);
}


/* OS_MTNAME -- Parse a filename to determine if the file is a magtape
 * device or something else.  A nonzero return indicates that the device
 * is a tape.
 */
static int
os_mtname (
  char	*fname,		/* filename e.g., "foo.tar" or "mua0:". */
  char	*osdev 		/* receives host system drive name */
)
{
#ifdef VMS
	register char	*ip;
	char	drive[SZ_FNAME+1];
#endif

	/* Ignore any "mt." prefix.  This is for backwards compatibility,
	 * to permit old-style names like "mt.MUA0:".
	 */
	if (!strncmp (fname, "mt.", 3) || !strncmp (fname, "MT.", 3))
	    fname += 3;

#ifdef VMS
	/* Resolve a possible logical device name. */
	if (strchr (fname, '['))
	    strcpy (drive, fname);
	else
	    _tranlog (fname, drive);

	/* If the resolved name ends with a colon it is a device name,
	 * which we assume to be a tape device.
	 */
	for (ip=drive;  *ip;  ip++)
	    ;
	if (*(ip-1) == ':') {
	    strcpy (osdev, drive);
	    return (1);
	}
#else
	/* For unix systems we assume anything beginning with /dev is a
	 * tape device.
	 */
	if (strncmp (fname, "/dev/", 5) == 0) {
	    strcpy (osdev, fname);
	    return (1);
	}
#endif

	strcpy (osdev, fname);
	return (0);
}