1 /* @(#)xio.c 1.20 09/07/18 Copyright 2003-2009 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static UConst char sccsid[] =
5 "@(#)xio.c 1.20 09/07/18 Copyright 2003-2009 J. Schilling";
6 #endif
7 /*
8 * EXtended I/O functions for cdrecord
9 *
10 * Copyright (c) 2003-2009 J. Schilling
11 */
12 /*
13 * The contents of this file are subject to the terms of the
14 * Common Development and Distribution License, Version 1.0 only
15 * (the "License"). You may not use this file except in compliance
16 * with the License.
17 *
18 * See the file CDDL.Schily.txt in this distribution for details.
19 * A copy of the CDDL is also available via the Internet at
20 * http://www.opensource.org/licenses/cddl1.txt
21 *
22 * When distributing Covered Code, include this CDDL HEADER in each
23 * file and include the License file CDDL.Schily.txt from this distribution.
24 */
25
26 #include <schily/mconfig.h>
27 #include <schily/unistd.h>
28 #include <schily/stdlib.h>
29 #include <schily/string.h>
30 #include <schily/standard.h>
31 #include <schily/fcntl.h>
32 #include <schily/io.h> /* for setmode() prototype */
33
34 #ifdef VMS
35 #include <vms_init.h>
36 #define open(n, p, m) (open)((n), (p), (m), \
37 "acc", acc_cb, &open_id)
38 #endif
39
40 #include "xio.h"
41
42 LOCAL xio_t x_stdin = {
43 NULL, /* x_next */
44 NULL, /* x_name */
45 0, /* x_off */
46 0, /* x_startoff */
47 STDIN_FILENO, /* x_file */
48 999, /* x_refcnt */
49 O_RDONLY, /* x_oflag */
50 0, /* x_omode */
51 0 /* x_xflags */
52 };
53
54 LOCAL xio_t *x_root = &x_stdin;
55 LOCAL xio_t **x_tail = NULL;
56
57
58 LOCAL xio_t *xnewnode __PR((char *name));
59 EXPORT void *xopen __PR((char *name, int oflag, int mode,
60 int xflags));
61 EXPORT off_t xmarkpos __PR((void *vp));
62 EXPORT int xclose __PR((void *vp));
63
64 LOCAL xio_t *
xnewnode(name)65 xnewnode(name)
66 char *name;
67 {
68 xio_t *xp;
69
70 if ((xp = malloc(sizeof (xio_t))) == NULL)
71 return ((xio_t *) NULL);
72
73 xp->x_next = (xio_t *) NULL;
74 xp->x_name = strdup(name);
75 if (xp->x_name == NULL) {
76 free(xp);
77 return ((xio_t *) NULL);
78 }
79 xp->x_off = 0;
80 xp->x_startoff = (off_t)0;
81 xp->x_file = -1;
82 xp->x_refcnt = 1;
83 xp->x_oflag = 0;
84 xp->x_omode = 0;
85 xp->x_xflags = 0;
86 return (xp);
87 }
88
89 EXPORT void *
xopen(name,oflag,mode,xflags)90 xopen(name, oflag, mode, xflags)
91 char *name;
92 int oflag;
93 int mode;
94 int xflags;
95 {
96 int f;
97 xio_t *xp;
98 xio_t *pp = x_root;
99
100 if (x_tail == NULL)
101 x_tail = &x_stdin.x_next;
102 if (name == NULL) {
103 xp = &x_stdin;
104 xp->x_refcnt++;
105 if ((oflag & O_BINARY) != 0) {
106 setmode(STDIN_FILENO, O_BINARY);
107 }
108 return (xp);
109 }
110 for (; pp; pp = pp->x_next) {
111 if (pp->x_name == NULL) /* stdin avoid core dump in strcmp() */
112 continue;
113 if ((strcmp(pp->x_name, name) == 0) &&
114 (pp->x_oflag == oflag) && (pp->x_omode == mode)) {
115 break;
116 }
117 }
118 if (pp) {
119 pp->x_refcnt++;
120 return ((void *)pp);
121 }
122 if ((f = open(name, oflag, mode)) < 0)
123 return (NULL);
124
125 if ((xp = xnewnode(name)) == NULL) {
126 close(f);
127 return (NULL);
128 }
129 xp->x_file = f;
130 xp->x_oflag = oflag;
131 xp->x_omode = mode;
132 xp->x_xflags = xflags & X_UFLAGS;
133 *x_tail = xp;
134 x_tail = &xp->x_next;
135 return ((void *)xp);
136 }
137
138 EXPORT off_t
xmarkpos(vp)139 xmarkpos(vp)
140 void *vp;
141 {
142 xio_t *xp = vp;
143 off_t off = (off_t)0;
144
145 if (xp == (xio_t *)NULL)
146 return ((off_t)-1);
147
148 xp->x_startoff = off = lseek(xp->x_file, (off_t)0, SEEK_CUR);
149 if (xp->x_startoff == (off_t)-1) {
150 xp->x_startoff = (off_t)0;
151 xp->x_xflags |= X_NOSEEK;
152 }
153 if (isatty(xp->x_file)) {
154 off = (off_t)-1;
155 xp->x_xflags |= X_NOSEEK;
156 }
157 return (off);
158 }
159
160 EXPORT int
xclose(vp)161 xclose(vp)
162 void *vp;
163 {
164 xio_t *xp = vp;
165 xio_t *pp = x_root;
166 int ret = 0;
167
168 if (xp == &x_stdin)
169 return (ret);
170 if (x_tail == NULL)
171 x_tail = &x_stdin.x_next;
172
173 /*error("xclose(%p) refcnt = %d\n", vp, xp->x_refcnt);*/
174 if (--xp->x_refcnt <= 0) {
175 ret = close(xp->x_file);
176 while (pp) {
177 if (pp->x_next == xp)
178 break;
179 if (pp->x_next == NULL)
180 break;
181 pp = pp->x_next;
182 }
183 if (pp->x_next == xp) {
184 if (x_tail == &xp->x_next)
185 x_tail = &pp->x_next;
186 pp->x_next = xp->x_next;
187 }
188
189 free(xp->x_name);
190 free(xp);
191 } else if ((xp->x_xflags & (X_NOREWIND|X_NOSEEK)) == 0) {
192 lseek(xp->x_file, xp->x_startoff, SEEK_SET);
193 }
194 return (ret);
195 }
196