1 /*
2 * This file has been modified for the cdrkit suite.
3 *
4 * The behaviour and appearence of the program code below can differ to a major
5 * extent from the version distributed by the original author(s).
6 *
7 * For details, see Changelog file distributed with the cdrkit package. If you
8 * received this file from another source then ask the distributing person for
9 * a log of modifications.
10 *
11 */
12
13 /* @(#)xio.c 1.11 04/07/11 Copyright 2003-2004 J. Schilling */
14 /*
15 * EXtended I/O functions for cdrecord
16 *
17 * Copyright (c) 2003-2004 J. Schilling
18 */
19 /*
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License version 2
22 * as published by the Free Software Foundation.
23 *
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
28 *
29 * You should have received a copy of the GNU General Public License along with
30 * this program; see the file COPYING. If not, write to the Free Software
31 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
32 */
33
34 #include <mconfig.h>
35 #include <unixstd.h>
36 #include <stdxlib.h>
37 #include <strdefs.h>
38 #include <standard.h>
39 #include <fctldefs.h>
40
41 #ifdef NEED_O_BINARY
42 #include <io.h> /* for setmode() prototype */
43 #endif
44
45 #include "xio.h"
46
47 static xio_t x_stdin = {
48 NULL, /* x_next */
49 NULL, /* x_name */
50 0, /* x_off */
51 STDIN_FILENO, /* x_file */
52 999, /* x_refcnt */
53 O_RDONLY, /* x_oflag */
54 0 /* x_omode */
55 };
56
57 static xio_t *x_root = &x_stdin;
58 static xio_t **x_tail = NULL;
59
60
61 static xio_t *xnewnode(char *name);
62 void *xopen(char *name, int oflag, int mode);
63 int xclose(void *vp);
64
65 static xio_t *
xnewnode(char * name)66 xnewnode(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_file = -1;
81 xp->x_refcnt = 1;
82 xp->x_oflag = 0;
83 xp->x_omode = 0;
84 return (xp);
85 }
86
87 void *
xopen(char * name,int oflag,int mode)88 xopen(char *name, int oflag, int mode)
89 {
90 int f;
91 xio_t *xp;
92 xio_t *pp = x_root;
93
94 if (x_tail == NULL)
95 x_tail = &x_stdin.x_next;
96 if (name == NULL) {
97 xp = &x_stdin;
98 xp->x_refcnt++;
99 #ifdef NEED_O_BINARY
100 if ((oflag & O_BINARY) != 0) {
101 setmode(STDIN_FILENO, O_BINARY);
102 }
103 #endif
104 return (xp);
105 }
106 for (; pp; pp = pp->x_next) {
107 if (pp->x_name == NULL) /* stdin avoid core dump in strcmp() */
108 continue;
109 if ((strcmp(pp->x_name, name) == 0) &&
110 (pp->x_oflag == oflag) && (pp->x_omode == mode)) {
111 break;
112 }
113 }
114 if (pp) {
115 pp->x_refcnt++;
116 return ((void *)pp);
117 }
118 if ((f = open(name, oflag, mode)) < 0)
119 return (NULL);
120
121 if ((xp = xnewnode(name)) == NULL) {
122 close(f);
123 return (NULL);
124 }
125 xp->x_file = f;
126 xp->x_oflag = oflag;
127 xp->x_omode = mode;
128 *x_tail = xp;
129 x_tail = &xp->x_next;
130 return ((void *)xp);
131 }
132
133 int
xclose(void * vp)134 xclose(void *vp)
135 {
136 xio_t *xp = vp;
137 xio_t *pp = x_root;
138 int ret = 0;
139
140 if (xp == &x_stdin)
141 return (ret);
142 if (x_tail == NULL)
143 x_tail = &x_stdin.x_next;
144
145 if (--xp->x_refcnt <= 0) {
146 ret = close(xp->x_file);
147 while (pp) {
148 if (pp->x_next == xp)
149 break;
150 if (pp->x_next == NULL)
151 break;
152 pp = pp->x_next;
153 }
154 if (pp->x_next == xp) {
155 if (x_tail == &xp->x_next)
156 x_tail = &pp->x_next;
157 pp->x_next = xp->x_next;
158 }
159
160 free(xp->x_name);
161 free(xp);
162 }
163 return (ret);
164 }
165