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