xref: /illumos-gate/usr/src/cmd/cdrw/util.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
30*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
31*7c478bd9Sstevel@tonic-gate #include <errno.h>
32*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
33*7c478bd9Sstevel@tonic-gate #include <string.h>
34*7c478bd9Sstevel@tonic-gate #include <unistd.h>
35*7c478bd9Sstevel@tonic-gate #include <libintl.h>
36*7c478bd9Sstevel@tonic-gate #include <time.h>
37*7c478bd9Sstevel@tonic-gate #include <pwd.h>
38*7c478bd9Sstevel@tonic-gate #include <auth_attr.h>
39*7c478bd9Sstevel@tonic-gate #include <auth_list.h>
40*7c478bd9Sstevel@tonic-gate #include <secdb.h>
41*7c478bd9Sstevel@tonic-gate 
42*7c478bd9Sstevel@tonic-gate #include "transport.h"
43*7c478bd9Sstevel@tonic-gate #include "util.h"
44*7c478bd9Sstevel@tonic-gate #include "mmc.h"
45*7c478bd9Sstevel@tonic-gate #include "msgs.h"
46*7c478bd9Sstevel@tonic-gate #include "misc_scsi.h"
47*7c478bd9Sstevel@tonic-gate #include "main.h"
48*7c478bd9Sstevel@tonic-gate #include "trackio.h"
49*7c478bd9Sstevel@tonic-gate #include "bstream.h"
50*7c478bd9Sstevel@tonic-gate 
51*7c478bd9Sstevel@tonic-gate char strbuf[81];
52*7c478bd9Sstevel@tonic-gate int priv_change_needed = 0;
53*7c478bd9Sstevel@tonic-gate 
54*7c478bd9Sstevel@tonic-gate void *
55*7c478bd9Sstevel@tonic-gate my_zalloc(size_t size)
56*7c478bd9Sstevel@tonic-gate {
57*7c478bd9Sstevel@tonic-gate 	void *ret;
58*7c478bd9Sstevel@tonic-gate 
59*7c478bd9Sstevel@tonic-gate 	ret = malloc(size);
60*7c478bd9Sstevel@tonic-gate 	if (ret == NULL) {
61*7c478bd9Sstevel@tonic-gate 
62*7c478bd9Sstevel@tonic-gate 		/* Lets wait a sec. and try again */
63*7c478bd9Sstevel@tonic-gate 		if (errno == EAGAIN) {
64*7c478bd9Sstevel@tonic-gate 			(void) sleep(1);
65*7c478bd9Sstevel@tonic-gate 			ret = malloc(size);
66*7c478bd9Sstevel@tonic-gate 		}
67*7c478bd9Sstevel@tonic-gate 
68*7c478bd9Sstevel@tonic-gate 		if (ret == NULL) {
69*7c478bd9Sstevel@tonic-gate 			(void) err_msg("%s\n", gettext(strerror(errno)));
70*7c478bd9Sstevel@tonic-gate 			(void) err_msg(gettext(
71*7c478bd9Sstevel@tonic-gate 			    "Memory allocation failure, Exiting...\n"));
72*7c478bd9Sstevel@tonic-gate 			exit(1);
73*7c478bd9Sstevel@tonic-gate 		}
74*7c478bd9Sstevel@tonic-gate 	}
75*7c478bd9Sstevel@tonic-gate 	(void) memset(ret, 0, size);
76*7c478bd9Sstevel@tonic-gate 	return (ret);
77*7c478bd9Sstevel@tonic-gate }
78*7c478bd9Sstevel@tonic-gate 
79*7c478bd9Sstevel@tonic-gate /*
80*7c478bd9Sstevel@tonic-gate  * Prints a string after going back pos number of steps.
81*7c478bd9Sstevel@tonic-gate  * Mainly used to show %age complete.
82*7c478bd9Sstevel@tonic-gate  */
83*7c478bd9Sstevel@tonic-gate int
84*7c478bd9Sstevel@tonic-gate str_print(char *str, int pos)
85*7c478bd9Sstevel@tonic-gate {
86*7c478bd9Sstevel@tonic-gate 	if ((pos > 0) && (pos < 80)) {
87*7c478bd9Sstevel@tonic-gate 		(void) memset(strbuf, 8, pos);
88*7c478bd9Sstevel@tonic-gate 		strbuf[pos] = 0;
89*7c478bd9Sstevel@tonic-gate 		(void) printf(strbuf);
90*7c478bd9Sstevel@tonic-gate 		(void) memset(strbuf, ' ', pos);
91*7c478bd9Sstevel@tonic-gate 		strbuf[pos] = 0;
92*7c478bd9Sstevel@tonic-gate 		(void) printf(strbuf);
93*7c478bd9Sstevel@tonic-gate 		(void) memset(strbuf, 8, pos);
94*7c478bd9Sstevel@tonic-gate 		strbuf[pos] = 0;
95*7c478bd9Sstevel@tonic-gate 		(void) printf(strbuf);
96*7c478bd9Sstevel@tonic-gate 	}
97*7c478bd9Sstevel@tonic-gate 
98*7c478bd9Sstevel@tonic-gate 	(void) printf("%s", str);
99*7c478bd9Sstevel@tonic-gate 	(void) fflush(stdout);
100*7c478bd9Sstevel@tonic-gate 	return (strlen(str));
101*7c478bd9Sstevel@tonic-gate }
102*7c478bd9Sstevel@tonic-gate 
103*7c478bd9Sstevel@tonic-gate /*
104*7c478bd9Sstevel@tonic-gate  * dump the trackio_error struct.
105*7c478bd9Sstevel@tonic-gate  */
106*7c478bd9Sstevel@tonic-gate void
107*7c478bd9Sstevel@tonic-gate print_trackio_error(struct trackio_error *te)
108*7c478bd9Sstevel@tonic-gate {
109*7c478bd9Sstevel@tonic-gate 	char *msg, *msg1;
110*7c478bd9Sstevel@tonic-gate 
111*7c478bd9Sstevel@tonic-gate 	msg = gettext("System could not supply data at the required rate.\n");
112*7c478bd9Sstevel@tonic-gate 	msg1 = gettext("Try using a lower speed for write\n");
113*7c478bd9Sstevel@tonic-gate 
114*7c478bd9Sstevel@tonic-gate 	switch (te->err_type) {
115*7c478bd9Sstevel@tonic-gate 	case TRACKIO_ERR_SYSTEM:
116*7c478bd9Sstevel@tonic-gate 		err_msg(gettext("System error: %s\n"), strerror(te->te_errno));
117*7c478bd9Sstevel@tonic-gate 		return;
118*7c478bd9Sstevel@tonic-gate 	case TRACKIO_ERR_TRANSPORT:
119*7c478bd9Sstevel@tonic-gate 		err_msg(gettext("Transport mechanism error:\n"));
120*7c478bd9Sstevel@tonic-gate 		if (te->status == 2) {
121*7c478bd9Sstevel@tonic-gate 			if ((te->key == 3) && (te->asc == 0x0c) &&
122*7c478bd9Sstevel@tonic-gate 			    (te->ascq == 9)) {
123*7c478bd9Sstevel@tonic-gate 				err_msg(msg);
124*7c478bd9Sstevel@tonic-gate 				err_msg(msg1);
125*7c478bd9Sstevel@tonic-gate 				return;
126*7c478bd9Sstevel@tonic-gate 			}
127*7c478bd9Sstevel@tonic-gate 			if (te->key == 3) {
128*7c478bd9Sstevel@tonic-gate 				err_msg(gettext("Bad media.\n"));
129*7c478bd9Sstevel@tonic-gate 				return;
130*7c478bd9Sstevel@tonic-gate 			}
131*7c478bd9Sstevel@tonic-gate 			if (debug) {
132*7c478bd9Sstevel@tonic-gate 				err_msg("Sense key %x, asc/asq %x/%x\n",
133*7c478bd9Sstevel@tonic-gate 				    te->key, te->asc, te->ascq);
134*7c478bd9Sstevel@tonic-gate 			} else {
135*7c478bd9Sstevel@tonic-gate 				err_msg(gettext("I/O error\n"));
136*7c478bd9Sstevel@tonic-gate 			}
137*7c478bd9Sstevel@tonic-gate 			return;
138*7c478bd9Sstevel@tonic-gate 		}
139*7c478bd9Sstevel@tonic-gate 		if (te->te_errno != 0)
140*7c478bd9Sstevel@tonic-gate 			err_msg("%s\n", strerror(te->te_errno));
141*7c478bd9Sstevel@tonic-gate 		return;
142*7c478bd9Sstevel@tonic-gate 	case TRACKIO_ERR_USER_ABORT:
143*7c478bd9Sstevel@tonic-gate 		err_msg(gettext("User abort.\n"));
144*7c478bd9Sstevel@tonic-gate 		return;
145*7c478bd9Sstevel@tonic-gate 	default:
146*7c478bd9Sstevel@tonic-gate 		err_msg(gettext("Unknown error type.\n"));
147*7c478bd9Sstevel@tonic-gate 		if (debug) {
148*7c478bd9Sstevel@tonic-gate 			err_msg("Trackio err type %d\n", te->err_type);
149*7c478bd9Sstevel@tonic-gate 		}
150*7c478bd9Sstevel@tonic-gate 	}
151*7c478bd9Sstevel@tonic-gate }
152*7c478bd9Sstevel@tonic-gate 
153*7c478bd9Sstevel@tonic-gate char *
154*7c478bd9Sstevel@tonic-gate get_err_str(void)
155*7c478bd9Sstevel@tonic-gate {
156*7c478bd9Sstevel@tonic-gate 	if (str_errno != 0)
157*7c478bd9Sstevel@tonic-gate 		return (str_errno_to_string(str_errno));
158*7c478bd9Sstevel@tonic-gate 	return (strerror(errno));
159*7c478bd9Sstevel@tonic-gate }
160*7c478bd9Sstevel@tonic-gate 
161*7c478bd9Sstevel@tonic-gate int
162*7c478bd9Sstevel@tonic-gate get_audio_type(char *ext)
163*7c478bd9Sstevel@tonic-gate {
164*7c478bd9Sstevel@tonic-gate 	if ((strcasecmp(ext, "au") == 0) ||
165*7c478bd9Sstevel@tonic-gate 	    (strcasecmp(ext, "sun") == 0))
166*7c478bd9Sstevel@tonic-gate 		return (AUDIO_TYPE_SUN);
167*7c478bd9Sstevel@tonic-gate 	if ((strcasecmp(ext, "wav") == 0) ||
168*7c478bd9Sstevel@tonic-gate 	    (strcasecmp(ext, "riff") == 0))
169*7c478bd9Sstevel@tonic-gate 		return (AUDIO_TYPE_WAV);
170*7c478bd9Sstevel@tonic-gate 	if (strcasecmp(ext, "cda") == 0)
171*7c478bd9Sstevel@tonic-gate 		return (AUDIO_TYPE_CDA);
172*7c478bd9Sstevel@tonic-gate 	if (strcasecmp(ext, "aur") == 0)
173*7c478bd9Sstevel@tonic-gate 		return (AUDIO_TYPE_AUR);
174*7c478bd9Sstevel@tonic-gate 
175*7c478bd9Sstevel@tonic-gate 	return (-1);
176*7c478bd9Sstevel@tonic-gate }
177*7c478bd9Sstevel@tonic-gate 
178*7c478bd9Sstevel@tonic-gate /*
179*7c478bd9Sstevel@tonic-gate  * common routines for showing progress.
180*7c478bd9Sstevel@tonic-gate  */
181*7c478bd9Sstevel@tonic-gate 
182*7c478bd9Sstevel@tonic-gate int progress_pos;
183*7c478bd9Sstevel@tonic-gate static uint64_t last_total;
184*7c478bd9Sstevel@tonic-gate time_t tm;
185*7c478bd9Sstevel@tonic-gate 
186*7c478bd9Sstevel@tonic-gate void
187*7c478bd9Sstevel@tonic-gate init_progress(void)
188*7c478bd9Sstevel@tonic-gate {
189*7c478bd9Sstevel@tonic-gate 	progress_pos = 0;
190*7c478bd9Sstevel@tonic-gate 	last_total = 0;
191*7c478bd9Sstevel@tonic-gate 	tm = time(NULL);
192*7c478bd9Sstevel@tonic-gate }
193*7c478bd9Sstevel@tonic-gate 
194*7c478bd9Sstevel@tonic-gate int
195*7c478bd9Sstevel@tonic-gate progress(void *arg, int64_t completed)
196*7c478bd9Sstevel@tonic-gate {
197*7c478bd9Sstevel@tonic-gate 	char s[BUFSIZE];
198*7c478bd9Sstevel@tonic-gate 	uint64_t total = (uintptr_t)arg & 0xffffffff;
199*7c478bd9Sstevel@tonic-gate 	if (completed == -1) {
200*7c478bd9Sstevel@tonic-gate 		/* Got ^C. Add 2 to progress pos to compensate for ^ and C */
201*7c478bd9Sstevel@tonic-gate 		progress_pos = str_print("(flushing ...)", progress_pos+2);
202*7c478bd9Sstevel@tonic-gate 		return (0);
203*7c478bd9Sstevel@tonic-gate 	}
204*7c478bd9Sstevel@tonic-gate 	if (total == 0) {
205*7c478bd9Sstevel@tonic-gate 		if (tm != time(NULL)) {
206*7c478bd9Sstevel@tonic-gate 			tm = time(NULL);
207*7c478bd9Sstevel@tonic-gate 			(void) snprintf(s, BUFSIZE,
208*7c478bd9Sstevel@tonic-gate 			    gettext("%d bytes written"), completed);
209*7c478bd9Sstevel@tonic-gate 
210*7c478bd9Sstevel@tonic-gate 			progress_pos = str_print(s, progress_pos);
211*7c478bd9Sstevel@tonic-gate 		}
212*7c478bd9Sstevel@tonic-gate 	} else {
213*7c478bd9Sstevel@tonic-gate 		total = (((uint64_t)completed) * 100)/total;
214*7c478bd9Sstevel@tonic-gate 		if (total == last_total)
215*7c478bd9Sstevel@tonic-gate 			return (0);
216*7c478bd9Sstevel@tonic-gate 		last_total = total;
217*7c478bd9Sstevel@tonic-gate 		if (total > 100) {
218*7c478bd9Sstevel@tonic-gate 			/* There is clearly a miscalculation somewhere */
219*7c478bd9Sstevel@tonic-gate 			if (debug)
220*7c478bd9Sstevel@tonic-gate 				(void) printf("\nWrote more than 100 %% !!\n");
221*7c478bd9Sstevel@tonic-gate 			return (0);
222*7c478bd9Sstevel@tonic-gate 		}
223*7c478bd9Sstevel@tonic-gate 		if (total == 100) {
224*7c478bd9Sstevel@tonic-gate 			/* l10n_NOTE : 'done' as in "Writing track 1...done"  */
225*7c478bd9Sstevel@tonic-gate 			(void) snprintf(s, BUFSIZE, gettext("done.\n"));
226*7c478bd9Sstevel@tonic-gate 		} else {
227*7c478bd9Sstevel@tonic-gate 			(void) snprintf(s, BUFSIZE, "%d %%", (uint_t)total);
228*7c478bd9Sstevel@tonic-gate 		}
229*7c478bd9Sstevel@tonic-gate 		progress_pos = str_print(s, progress_pos);
230*7c478bd9Sstevel@tonic-gate 	}
231*7c478bd9Sstevel@tonic-gate 	return (0);
232*7c478bd9Sstevel@tonic-gate }
233*7c478bd9Sstevel@tonic-gate 
234*7c478bd9Sstevel@tonic-gate void
235*7c478bd9Sstevel@tonic-gate raise_priv(void)
236*7c478bd9Sstevel@tonic-gate {
237*7c478bd9Sstevel@tonic-gate 	if (priv_change_needed && (cur_uid != 0)) {
238*7c478bd9Sstevel@tonic-gate 		if (seteuid(0) == 0)
239*7c478bd9Sstevel@tonic-gate 			cur_uid = 0;
240*7c478bd9Sstevel@tonic-gate 	}
241*7c478bd9Sstevel@tonic-gate }
242*7c478bd9Sstevel@tonic-gate 
243*7c478bd9Sstevel@tonic-gate void
244*7c478bd9Sstevel@tonic-gate lower_priv(void)
245*7c478bd9Sstevel@tonic-gate {
246*7c478bd9Sstevel@tonic-gate 	if (priv_change_needed && (cur_uid == 0)) {
247*7c478bd9Sstevel@tonic-gate 		if (seteuid(ruid) == 0)
248*7c478bd9Sstevel@tonic-gate 			cur_uid = ruid;
249*7c478bd9Sstevel@tonic-gate 	}
250*7c478bd9Sstevel@tonic-gate }
251*7c478bd9Sstevel@tonic-gate 
252*7c478bd9Sstevel@tonic-gate int
253*7c478bd9Sstevel@tonic-gate check_auth(uid_t uid)
254*7c478bd9Sstevel@tonic-gate {
255*7c478bd9Sstevel@tonic-gate 	struct passwd *pw;
256*7c478bd9Sstevel@tonic-gate 
257*7c478bd9Sstevel@tonic-gate 
258*7c478bd9Sstevel@tonic-gate 	pw = getpwuid(uid);
259*7c478bd9Sstevel@tonic-gate 
260*7c478bd9Sstevel@tonic-gate 	if (pw == NULL) {
261*7c478bd9Sstevel@tonic-gate 		/* fail if we cannot get password entry */
262*7c478bd9Sstevel@tonic-gate 		return (0);
263*7c478bd9Sstevel@tonic-gate 	}
264*7c478bd9Sstevel@tonic-gate 
265*7c478bd9Sstevel@tonic-gate 	/*
266*7c478bd9Sstevel@tonic-gate 	 * check in the RBAC authority files to see if
267*7c478bd9Sstevel@tonic-gate 	 * the user has permission to use CDRW
268*7c478bd9Sstevel@tonic-gate 	 */
269*7c478bd9Sstevel@tonic-gate 	if (chkauthattr(CDRW_AUTH, pw->pw_name) != 1) {
270*7c478bd9Sstevel@tonic-gate 		/* user is not in database, return failure */
271*7c478bd9Sstevel@tonic-gate 		return (0);
272*7c478bd9Sstevel@tonic-gate 	} else {
273*7c478bd9Sstevel@tonic-gate 		return (1);
274*7c478bd9Sstevel@tonic-gate 	}
275*7c478bd9Sstevel@tonic-gate }
276*7c478bd9Sstevel@tonic-gate 
277*7c478bd9Sstevel@tonic-gate /*
278*7c478bd9Sstevel@tonic-gate  * This will busy delay in ms milliseconds. Needed for cases
279*7c478bd9Sstevel@tonic-gate  * where 1 sec wait is too long. This is needed for some newer
280*7c478bd9Sstevel@tonic-gate  * drives which can empty the drive cache very quickly.
281*7c478bd9Sstevel@tonic-gate  */
282*7c478bd9Sstevel@tonic-gate void
283*7c478bd9Sstevel@tonic-gate ms_delay(uint_t ms)
284*7c478bd9Sstevel@tonic-gate {
285*7c478bd9Sstevel@tonic-gate 
286*7c478bd9Sstevel@tonic-gate 	hrtime_t start, req;
287*7c478bd9Sstevel@tonic-gate 
288*7c478bd9Sstevel@tonic-gate 	start = gethrtime();
289*7c478bd9Sstevel@tonic-gate 	req = start + ((hrtime_t)ms * 1000000);
290*7c478bd9Sstevel@tonic-gate 
291*7c478bd9Sstevel@tonic-gate 	while (gethrtime() < req)
292*7c478bd9Sstevel@tonic-gate 		yield();
293*7c478bd9Sstevel@tonic-gate }
294