1 /*
2   Copyright (C) 2004, 2008, 2010-2011, 2017 Rocky Bernstein <rocky@gnu.org>
3   Copyright (C) 2014 Robert Kausch <robert.kausch@freac.org>
4   Copyright (C) 1998 Monty xiphmont@mit.edu
5 
6   This program is free software: you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation, either version 3 of the License, or
9   (at your option) any later version.
10 
11   This program is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15 
16   You should have received a copy of the GNU General Public License
17   along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #ifdef HAVE_CONFIG_H
21 # include "config.h"
22 # define __CDIO_CONFIG_H__ 1
23 #endif
24 
25 #ifdef HAVE_SYS_TIME_H
26 # include <sys/time.h>
27 #endif
28 
29 #include "common_interface.h"
30 #include "utils.h"
31 void
cderror(cdrom_drive_t * d,const char * s)32 cderror(cdrom_drive_t *d,const char *s)
33 {
34   ssize_t bytes_ret __attribute__((unused));
35   if(s && d){
36     switch(d->errordest){
37     case CDDA_MESSAGE_PRINTIT:
38       bytes_ret = write(STDERR_FILENO, s, strlen(s));
39       if (strlen(s) != bytes_ret)
40 
41       break;
42     case CDDA_MESSAGE_LOGIT:
43       d->errorbuf=catstring(d->errorbuf,s);
44       break;
45     case CDDA_MESSAGE_FORGETIT:
46     default:
47       break;
48     }
49   }
50 }
51 
52 void
cdmessage(cdrom_drive_t * d,const char * s)53 cdmessage(cdrom_drive_t *d, const char *s)
54 {
55   ssize_t bytes_ret __attribute__((unused));
56   if(s && d){
57     switch(d->messagedest){
58     case CDDA_MESSAGE_PRINTIT:
59       bytes_ret = write(STDERR_FILENO, s, strlen(s));
60       break;
61     case CDDA_MESSAGE_LOGIT:
62       d->messagebuf=catstring(d->messagebuf,s);
63       break;
64     case CDDA_MESSAGE_FORGETIT:
65     default:
66       break;
67     }
68   }
69 }
70 
71 void
idperror(int messagedest,char ** messages,const char * f,const char * s)72 idperror(int messagedest,char **messages,const char *f,
73 	 const char *s)
74 {
75 
76   char *buffer;
77   int malloced=0;
78   if(!f)
79     buffer=(char *)s;
80   else
81     if(!s)
82       buffer=(char *)f;
83     else{
84       buffer=malloc(strlen(f)+strlen(s)+9);
85       sprintf(buffer,f,s);
86       malloced=1;
87     }
88 
89   if(buffer){
90     ssize_t bytes_ret __attribute__((unused));
91     switch(messagedest){
92     case CDDA_MESSAGE_PRINTIT:
93       bytes_ret = write(STDERR_FILENO,buffer,strlen(buffer));
94       if(errno){
95 	bytes_ret = write(STDERR_FILENO,": ",2);
96 	bytes_ret = write(STDERR_FILENO,strerror(errno),strlen(strerror(errno)));
97 	bytes_ret = write(STDERR_FILENO,"\n",1);
98       }
99       break;
100     case CDDA_MESSAGE_LOGIT:
101       if(messages){
102 	*messages=catstring(*messages,buffer);
103 	if(errno){
104 	  *messages=catstring(*messages,": ");
105 	  *messages=catstring(*messages,strerror(errno));
106 	  *messages=catstring(*messages,"\n");
107 	}
108       }
109       break;
110     case CDDA_MESSAGE_FORGETIT:
111     default:
112       break;
113     }
114   }
115   if(malloced)free(buffer);
116 }
117 
118 void
idmessage(int messagedest,char ** messages,const char * f,const char * s)119 idmessage(int messagedest,char **messages,const char *f,
120 	  const char *s)
121 {
122   char *buffer;
123   int malloced=0;
124   ssize_t bytes_ret __attribute__((unused));
125   if(!f)
126     buffer=(char *)s;
127   else
128     if(!s)
129       buffer=(char *)f;
130     else{
131       const unsigned int i_buffer=strlen(f)+strlen(s)+2;
132       buffer=malloc(i_buffer);
133       sprintf(buffer,f,s);
134       strncat(buffer,"\n",1);
135       malloced=1;
136     }
137 
138   if(buffer) {
139     switch(messagedest){
140     case CDDA_MESSAGE_PRINTIT:
141       bytes_ret = write(STDERR_FILENO,buffer,strlen(buffer));
142       if(!malloced)
143 	 bytes_ret = write(STDERR_FILENO,"\n",1);
144       break;
145     case CDDA_MESSAGE_LOGIT:
146       if(messages){
147 	*messages=catstring(*messages,buffer);
148 	if(!malloced)*messages=catstring(*messages,"\n");
149 	}
150       break;
151     case CDDA_MESSAGE_FORGETIT:
152     default:
153       break;
154     }
155   }
156   if(malloced)free(buffer);
157 }
158 
159 char *
catstring(char * buff,const char * s)160 catstring(char *buff, const char *s) {
161   if (s) {
162     const unsigned int add_len = strlen(s) + 1;
163     if(buff) {
164       buff = realloc(buff, strlen(buff) + add_len);
165     } else {
166       buff=calloc(add_len, 1);
167     }
168     strncat(buff, s, add_len - 1);
169   }
170   return(buff);
171 }
172 
173 int
gettime(struct timespec * ts)174 gettime(struct timespec *ts) {
175   int ret = -1;
176   if (!ts) return ret;
177 
178 #if defined(HAVE_CLOCK_GETTIME)
179   /* Use clock_gettime if available, preferably using the monotonic clock.
180    */
181   static clockid_t clock = (clockid_t)-1;
182   if ((int)clock == -1) clock = (clock_gettime(CLOCK_MONOTONIC, ts) < 0 ? CLOCK_REALTIME : CLOCK_MONOTONIC);
183   ret = clock_gettime(clock, ts);
184 #elif defined(WIN32)
185   /* clock() returns wall time (not CPU time) on Windows, so we can use it here.
186    */
187   clock_t time = clock();
188   if ((int)time != -1) {
189     ts->tv_sec  = time/CLOCKS_PER_SEC;
190     ts->tv_nsec = time%CLOCKS_PER_SEC*(1000000000/CLOCKS_PER_SEC);
191     ret = 0;
192   }
193 #else
194   /* In other cases use gettimeofday.
195    */
196   struct timeval tv;
197   ret = gettimeofday(&tv, NULL);
198   if (ret == 0) {
199     ts->tv_sec  = tv.tv_sec;
200     ts->tv_nsec = tv.tv_usec*1000;
201   }
202 #endif
203 
204   return ret;
205 }
206