Imported Upstream version 1.1.11
[platform/upstream/cdrkit.git] / wodim / xio.c
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 *
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 *
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
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 }