1 /* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
2 
3 /*
4    Copyright (c) 2006 - 2013 Thomas Schmitt <scdbackup@gmx.net>
5    Provided under GPL version 2 or later
6         and under FreeBSD license revised, i.e. without advertising clause.
7 */
8 
9 #ifdef HAVE_CONFIG_H
10 #include "../config.h"
11 #endif
12 
13 #include <errno.h>
14 #include <unistd.h>
15 #include <stdio.h>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <fcntl.h>
19 #include <sys/ioctl.h>
20 #include <sys/file.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sys/poll.h>
24 #include <camlib.h>
25 #include <cam/scsi/scsi_message.h>
26 #include <cam/scsi/scsi_pass.h>
27 
28 #include <err.h> /* XXX */
29 
30 /* ts A70909 */
31 #include <sys/statvfs.h>
32 
33 /* ts B00121 */
34 #include <sys/disk.h> /* DIOCGMEDIASIZE */
35 
36 
37 /* ts B00326 : For use of CAM_PASS_ERR_RECOVER with ahci */
38 #define Libburn_for_freebsd_ahcI yes
39 
40 /* ts B00327 : for debugging of cam_send_cdb() failures
41  # define Libburn_ahci_verbouS yes
42 */
43 
44 /* ts B00327 : Apply CAM_PASS_ERR_RECOVER to drives even if not ahci
45  # define libburn_ahci_style_for_alL yes
46 */
47 
48 
49 #include "transport.h"
50 #include "drive.h"
51 #include "sg.h"
52 #include "spc.h"
53 #include "mmc.h"
54 #include "sbc.h"
55 #include "debug.h"
56 #include "toc.h"
57 #include "util.h"
58 #include "init.h"
59 
60 #include "libdax_msgs.h"
61 extern struct libdax_msgs *libdax_messenger;
62 
63 struct burn_drive_enumeration_state {
64 	int fd;
65 	union ccb ccb;
66 	unsigned int i;
67 	int skip_device;
68 };
69 
70 static void enumerate_common(char *fname, int bus_no, int host_no,
71 			     int channel_no, int target_no, int lun_no);
72 
73 /* ts A51221 */
74 int burn_drive_is_banned(char *device_address);
75 
76 
77 /* ts A60821
78    debug: for tracing calls which might use open drive fds
79           or for catching SCSI usage of emulated drives. */
80 int mmc_function_spy(struct burn_drive *d, char * text);
81 
82 
83 /* ts B00113
84    Whether to log SCSI commands:
85    bit0= log in /tmp/libburn_sg_command_log
86    bit1= log to stderr
87    bit2= flush every line
88 */
89 extern int burn_sg_log_scsi;
90 
91 /* ts B00114 */
92 /* Storage object is in libburn/init.c
93    whether to strive for exclusive access to the drive
94 */
95 extern int burn_sg_open_o_excl;
96 
97 
98 /* ts A91227 */
99 /** Returns the id string  of the SCSI transport adapter and eventually
100     needed operating system facilities.
101     This call is usable even if sg_initialize() was not called yet. In that
102     case a preliminary constant message might be issued if detailed info is
103     not available yet.
104     @param msg   returns id string
105     @param flag  unused yet, submit 0
106     @return      1 = success, <=0 = failure
107 */
sg_id_string(char msg[1024],int flag)108 int sg_id_string(char msg[1024], int flag)
109 {
110 	strcpy(msg, "internal FreeBSD CAM adapter sg-freebsd");
111 	return 1;
112 }
113 
114 
115 /* ts A91227 */
116 /** Performs global initialization of the SCSI transport adapter and eventually
117     needed operating system facilities. Checks for compatibility supporting
118     software components.
119     @param msg   returns ids and/or error messages of eventual helpers
120     @param flag  unused yet, submit 0
121     @return      1 = success, <=0 = failure
122 */
sg_initialize(char msg[1024],int flag)123 int sg_initialize(char msg[1024], int flag)
124 {
125 	return sg_id_string(msg, 0);
126 }
127 
128 
129 /* ts A91227 */
130 /** Performs global finalization of the SCSI transport adapter and eventually
131     needed operating system facilities. Releases globally acquired resources.
132     @param flag  unused yet, submit 0
133     @return      1 = success, <=0 = failure
134 */
sg_shutdown(int flag)135 int sg_shutdown(int flag)
136 {
137 	return 1;
138 }
139 
140 
141 /** Finalizes BURN_OS_TRANSPORT_DRIVE_ELEMENTS, the components of
142     struct burn_drive which are defined in os-*.h.
143     The eventual initialization of those components was made underneath
144     scsi_enumerate_drives().
145     This will be called when a burn_drive gets disposed.
146     @param d     the drive to be finalized
147     @param flag  unused yet, submit 0
148     @return      1 = success, <=0 = failure
149 */
sg_dispose_drive(struct burn_drive * d,int flag)150 int sg_dispose_drive(struct burn_drive *d, int flag)
151 {
152         return 1;
153 }
154 
155 
156 /* ts A61021 : Moved most code from scsi_enumerate_drives under
157                sg_give_next_adr() */
158 /* Some helper functions for scsi_give_next_adr() */
159 
sg_init_enumerator(burn_drive_enumerator_t * idx_)160 static int sg_init_enumerator(burn_drive_enumerator_t *idx_)
161 {
162 	struct burn_drive_enumeration_state *idx;
163 	int bufsize;
164 
165 	idx = calloc(1, sizeof(*idx));
166 	if (idx == NULL) {
167 		warnx("cannot allocate memory for enumerator");
168 		return -1;
169 	}
170 	idx->skip_device = 0;
171 
172 	if ((idx->fd = open(XPT_DEVICE, O_RDWR)) == -1) {
173 		warn("could not open %s", XPT_DEVICE);
174 		free(idx);
175 		idx = NULL;
176 		return -1;
177 	}
178 
179 	memset(&(idx->ccb), 0, sizeof(union ccb));
180 
181 	idx->ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
182 	idx->ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
183 	idx->ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
184 
185 	idx->ccb.ccb_h.func_code = XPT_DEV_MATCH;
186 	bufsize = sizeof(struct dev_match_result) * 100;
187 	idx->ccb.cdm.match_buf_len = bufsize;
188 	idx->ccb.cdm.matches = (struct dev_match_result *) calloc(1, bufsize);
189 	if (idx->ccb.cdm.matches == NULL) {
190 		warnx("cannot allocate memory for matches");
191 		close(idx->fd);
192 		free(idx);
193 		return -1;
194 	}
195 	idx->ccb.cdm.num_matches = 0;
196 	idx->i = idx->ccb.cdm.num_matches; /* to trigger buffer load */
197 
198 	/*
199 	 * We fetch all nodes, since we display most of them in the default
200 	 * case, and all in the verbose case.
201 	 */
202 	idx->ccb.cdm.num_patterns = 0;
203 	idx->ccb.cdm.pattern_buf_len = 0;
204 
205 	*idx_ = idx;
206 
207 	return 1;
208 }
209 
sg_destroy_enumerator(burn_drive_enumerator_t * idx_)210 static void sg_destroy_enumerator(burn_drive_enumerator_t *idx_)
211 {
212 	struct burn_drive_enumeration_state *idx = *idx_;
213 
214 	if(idx->fd != -1)
215 		close(idx->fd);
216 
217 	free(idx->ccb.cdm.matches);
218 	free(idx);
219 
220 	*idx_ = NULL;
221 }
222 
sg_next_enumeration_buffer(burn_drive_enumerator_t * idx_)223 static int sg_next_enumeration_buffer(burn_drive_enumerator_t *idx_)
224 {
225 	struct burn_drive_enumeration_state *idx = *idx_;
226 
227 	/*
228 	 * We do the ioctl multiple times if necessary, in case there are
229 	 * more than 100 nodes in the EDT.
230 	 */
231 	if (ioctl(idx->fd, CAMIOCOMMAND, &(idx->ccb)) == -1) {
232 		warn("error sending CAMIOCOMMAND ioctl");
233 		return -1;
234 	}
235 
236 	if ((idx->ccb.ccb_h.status != CAM_REQ_CMP)
237 	    || ((idx->ccb.cdm.status != CAM_DEV_MATCH_LAST)
238 		&& (idx->ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
239 		warnx("got CAM error %#x, CDM error %d\n",
240 		      idx->ccb.ccb_h.status, idx->ccb.cdm.status);
241 		return -1;
242 	}
243 	return 1;
244 }
245 
246 
247 /** Returns the next index object state and the next enumerated drive address.
248     @param idx An opaque handle. Make no own theories about it.
249     @param adr Takes the reply
250     @param adr_size Gives maximum size of reply including final 0
251     @param initialize  1 = start new,
252                        0 = continue, use no other values for now
253                       -1 = finish
254     @return 1 = reply is a valid address , 0 = no further address available
255            -1 = severe error (e.g. adr_size too small)
256 */
sg_give_next_adr(burn_drive_enumerator_t * idx_,char adr[],int adr_size,int initialize)257 int sg_give_next_adr(burn_drive_enumerator_t *idx_,
258 		     char adr[], int adr_size, int initialize)
259 {
260 	struct burn_drive_enumeration_state *idx;
261 	int ret;
262 
263 	if (initialize == 1) {
264 		ret = sg_init_enumerator(idx_);
265 		if (ret<=0)
266 			return ret;
267 	} else if (initialize == -1) {
268 		sg_destroy_enumerator(idx_);
269 		return 0;
270 	}
271 
272 	idx = *idx_;
273 
274 	do {
275 		if (idx->i >= idx->ccb.cdm.num_matches) {
276 			ret = sg_next_enumeration_buffer(idx_);
277 			if (ret<=0)
278 				return -1;
279 			idx->i = 0;
280 		} else
281 			(idx->i)++;
282 
283 		while (idx->i < idx->ccb.cdm.num_matches) {
284 			switch (idx->ccb.cdm.matches[idx->i].type) {
285 			case DEV_MATCH_BUS:
286 				break;
287 			case DEV_MATCH_DEVICE: {
288 				struct device_match_result* result;
289 
290 				result = &(idx->ccb.cdm.matches[idx->i].result.device_result);
291 				if (result->flags & DEV_RESULT_UNCONFIGURED)
292 					idx->skip_device = 1;
293 				else
294 					idx->skip_device = 0;
295 				break;
296 			}
297 			case DEV_MATCH_PERIPH: {
298 				struct periph_match_result* result;
299 
300 				result = &(idx->ccb.cdm.matches[idx->i].result.periph_result);
301 /* ts B00112 : we really want only "cd" devices.
302 
303 				if (idx->skip_device ||
304 				    strcmp(result->periph_name, "pass") == 0)
305 					break;
306 */
307 				if (idx->skip_device ||
308 				    strcmp(result->periph_name, "cd") != 0)
309 					break;
310 				ret = snprintf(adr, adr_size, "/dev/%s%d",
311 					 result->periph_name, result->unit_number);
312 				if(ret >= adr_size)
313 					return -1;
314 
315 				/* Found next enumerable address */
316 				return 1;
317 
318 			}
319 			default:
320 				/* fprintf(stderr, "unknown match type\n"); */
321 				break;
322 			}
323 			(idx->i)++;
324 		}
325 	} while ((idx->ccb.ccb_h.status == CAM_REQ_CMP)
326 		&& (idx->ccb.cdm.status == CAM_DEV_MATCH_MORE));
327 
328 	return 0;
329 }
330 
331 
sg_is_enumerable_adr(char * adr)332 int sg_is_enumerable_adr(char* adr)
333 {
334 	burn_drive_enumerator_t idx;
335 	int ret;
336 	char buf[64];
337 
338 	ret = sg_init_enumerator(&idx);
339 	if (ret <= 0)
340 		return 0;
341 	while(1) {
342 		ret = sg_give_next_adr(&idx, buf, sizeof(buf), 0);
343 		if (ret <= 0)
344 			break;
345 		if (strcmp(adr, buf) == 0) {
346 			sg_destroy_enumerator(&idx);
347 			return 1;
348 		}
349 	}
350 	sg_destroy_enumerator(&idx);
351 	return (0);
352 }
353 
354 
355 /** Try to obtain SCSI address parameters.
356     @return  1 is success , 0 is failure
357 */
sg_obtain_scsi_adr(char * path,int * bus_no,int * host_no,int * channel_no,int * target_no,int * lun_no)358 int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
359                        int *target_no, int *lun_no)
360 {
361 	burn_drive_enumerator_t idx;
362 	int ret;
363 	char buf[64];
364 	struct periph_match_result* result;
365 
366 	ret = sg_init_enumerator(&idx);
367 	if (ret <= 0)
368 		return 0;
369 	while(1) {
370 		ret = sg_give_next_adr(&idx, buf, sizeof(buf), 0);
371 		if (ret <= 0)
372 			break;
373 		if (strcmp(path, buf) == 0) {
374 			result = &(idx->ccb.cdm.matches[idx->i].result.periph_result);
375 			*bus_no = result->path_id;
376 			*host_no = result->path_id;
377 			*channel_no = 0;
378 			*target_no = result->target_id;
379 			*lun_no = result->target_lun;
380 			sg_destroy_enumerator(&idx);
381 			return 1;
382 		}
383 	}
384 	sg_destroy_enumerator(&idx);
385 	return (0);
386 }
387 
388 
sg_close_drive(struct burn_drive * d)389 int sg_close_drive(struct burn_drive * d)
390 {
391 	if (d->cam != NULL) {
392 		cam_close_device(d->cam);
393 		d->cam = NULL;
394 	}
395 	if (d->lock_fd > 0) {
396 		close(d->lock_fd);
397 		d->lock_fd = -1;
398 	}
399 	return 0;
400 }
401 
sg_drive_is_open(struct burn_drive * d)402 int sg_drive_is_open(struct burn_drive * d)
403 {
404 	return (d->cam != NULL);
405 }
406 
scsi_enumerate_drives(void)407 int scsi_enumerate_drives(void)
408 {
409 	burn_drive_enumerator_t idx;
410 	int ret;
411 	char buf[64];
412 	struct periph_match_result* result;
413 
414 	ret = sg_init_enumerator(&idx);
415 	if (ret <= 0)
416 		return 0;
417 	while(1) {
418 		ret = sg_give_next_adr(&idx, buf, sizeof(buf), 0);
419 		if (ret <= 0)
420 			break;
421 		if (burn_drive_is_banned(buf))
422 			continue;
423 		result = &idx->ccb.cdm.matches[idx->i].result.periph_result;
424 		enumerate_common(buf, result->path_id, result->path_id,
425 				0, result->target_id,
426 				result->target_lun);
427 	}
428 	sg_destroy_enumerator(&idx);
429 
430 	return 1;
431 }
432 
433 
434 #ifdef Scsi_freebsd_make_own_enumeratE
435 
436 /* ts A61021: The old version which mixes SCSI and operating system adapter
437 */
enumerate_common(char * fname,int bus_no,int host_no,int channel_no,int target_no,int lun_no)438 static void enumerate_common(char *fname, int bus_no, int host_no,
439 			     int channel_no, int target_no, int lun_no)
440 {
441 	struct burn_drive *t;
442 	struct burn_drive out;
443 
444 	/* Initialize pointers to managed memory */
445 	out.devname = NULL;
446 	out.idata = NULL;
447 	out.mdata = NULL;
448 
449 	/* ts A60923 */
450 	out.bus_no = bus_no;
451 	out.host = host_no;
452 	out.id = target_no;
453 	out.channel = channel_no;
454 	out.lun = lun_no;
455 
456 	out.devname = strdup(fname);
457 	if (out.devname == NULL)
458 		goto could_not_allocate;
459 
460 	out.cam = NULL;
461 	out.lock_fd = -1;
462 	out.is_ahci = 0;
463 
464 	out.start_lba= -2000000000;
465 	out.end_lba= -2000000000;
466 	out.read_atip = mmc_read_atip;
467 
468 	out.grab = sg_grab;
469 	out.release = sg_release;
470 	out.drive_is_open= sg_drive_is_open;
471 	out.issue_command = sg_issue_command;
472 	out.getcaps = spc_getcaps;
473 	out.released = 1;
474 	out.status = BURN_DISC_UNREADY;
475 
476 	out.eject = sbc_eject;
477 	out.load = sbc_load;
478 	out.lock = spc_prevent;
479 	out.unlock = spc_allow;
480 	out.read_disc_info = spc_sense_write_params;
481 	out.get_erase_progress = spc_get_erase_progress;
482 	out.test_unit_ready = spc_test_unit_ready;
483 	out.probe_write_modes = spc_probe_write_modes;
484 	out.read_toc = mmc_read_toc;
485 	out.write = mmc_write;
486 	out.erase = mmc_erase;
487 	out.read_cd = mmc_read_cd;
488 	out.perform_opc = mmc_perform_opc;
489 	out.set_speed = mmc_set_speed;
490 	out.send_parameters = spc_select_error_params;
491 	out.send_write_parameters = spc_select_write_params;
492 	out.send_cue_sheet = mmc_send_cue_sheet;
493 	out.sync_cache = mmc_sync_cache;
494 	out.get_nwa = mmc_get_nwa;
495 	out.close_disc = mmc_close_disc;
496 	out.close_session = mmc_close_session;
497 	out.close_track_session = mmc_close;
498 	out.read_buffer_capacity = mmc_read_buffer_capacity;
499 	out.idata = calloc(1, sizeof(struct burn_scsi_inquiry_data));
500 	out.idata->valid = 0;
501 	out.mdata = calloc(1, sizeof(struct scsi_mode_data));
502 	if (out.idata == NULL || out.mdata == NULL) {
503 could_not_allocate:;
504 		libdax_msgs_submit(libdax_messenger, -1, 0x00020108,
505 			LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
506 			"Could not allocate new drive object", 0, 0);
507 		if (out.devname != NULL)
508 			free(out.devname);
509 		out.devname = NULL;
510 		if (out.idata != NULL)
511 			free(out.idata);
512 		out.idata = NULL;
513 		if (out.mdata != NULL)
514 			free(out.mdata);
515 		out.mdata = NULL;
516 		return;
517 	}
518 	out.mdata->p2a_valid = 0;
519 	memset(&out.params, 0, sizeof(struct params));
520 	t = burn_drive_register(&out);
521 
522 /* ts A60821
523    <<< debug: for tracing calls which might use open drive fds */
524 	mmc_function_spy(NULL, "enumerate_common : -------- doing grab");
525 
526 /* try to get the drive info */
527 	if (t->grab(t)) {
528 		t->getcaps(t);
529 		t->unlock(t);
530 		t->released = 1;
531 	}
532 
533 /* ts A60821
534    <<< debug: for tracing calls which might use open drive fds */
535 	mmc_function_spy(NULL, "enumerate_common : ----- would release ");
536 
537 }
538 
539 #else /* Scsi_freebsd_make_own_enumeratE */
540 
541 /* The new, more concise version of enumerate_common */
enumerate_common(char * fname,int bus_no,int host_no,int channel_no,int target_no,int lun_no)542 static void enumerate_common(char *fname, int bus_no, int host_no,
543 			     int channel_no, int target_no, int lun_no)
544 {
545 	int ret;
546 	struct burn_drive out;
547 
548 	/* General libburn drive setup */
549 	burn_setup_drive(&out, fname);
550 
551 	/* This transport adapter uses SCSI-family commands and models
552 	   (seems the adapter would know better than its boss, if ever) */
553 	ret = burn_scsi_setup_drive(&out, bus_no, host_no, channel_no,
554                                  target_no, lun_no, 0);
555         if (ret<=0)
556                 return;
557 
558 	/* Operating system adapter is CAM */
559 	/* Adapter specific handles and data */
560 	out.cam = NULL;
561 	out.lock_fd = -1;
562 	out.is_ahci = 0;
563 
564 	/* Adapter specific functions */
565 	out.grab = sg_grab;
566 	out.release = sg_release;
567 	out.drive_is_open = sg_drive_is_open;
568 	out.issue_command = sg_issue_command;
569 
570 	/* Finally register drive and inquire drive information */
571 	burn_drive_finish_enum(&out);
572 }
573 
574 #endif /* ! Scsi_freebsd_make_own_enumeratE */
575 
576 
577 /* Lock the inode associated to dev_fd and the inode associated to devname.
578    Return OS errno, number of pass device of dev_fd, locked fd to devname,
579    error message.
580    A return value of > 0 means success, <= 0 means failure.
581 */
freebsd_dev_lock(int dev_fd,char * devname,int * os_errno,int * pass_dev_no,int * lock_fd,char msg[4096],int flag)582 static int freebsd_dev_lock(int dev_fd, char *devname,
583 	 int *os_errno, int *pass_dev_no, int *lock_fd, char msg[4096],
584 	 int flag)
585 {
586 	int lock_denied = 0, fd_stbuf_valid, name_stbuf_valid, i, pass_l = 100;
587 	int max_retry = 3, tries = 0;
588 	struct stat fd_stbuf, name_stbuf;
589 	char pass_name[16], *lock_name;
590 
591 	*os_errno = 0;
592 	*pass_dev_no = -1;
593 	*lock_fd = -1;
594 	msg[0] = 0;
595 
596 	fd_stbuf_valid = !fstat(dev_fd, &fd_stbuf);
597 
598 	/* Try to find name of pass device by inode number */
599 	lock_name = (char *) "effective device";
600 	if(fd_stbuf_valid) {
601 		for (i = 0; i < pass_l; i++) {
602 			sprintf(pass_name, "/dev/pass%d", i);
603 			if (stat(pass_name, &name_stbuf) != -1)
604 				if(fd_stbuf.st_ino == name_stbuf.st_ino &&
605 			   	fd_stbuf.st_dev == name_stbuf.st_dev)
606 		break;
607 		}
608 		if (i < pass_l) {
609 			lock_name = pass_name;
610 			*pass_dev_no = i;
611 		}
612 	}
613 
614 	name_stbuf_valid = !stat(devname, &name_stbuf);
615 	for (tries= 0; tries <= max_retry; tries++) {
616 		lock_denied = flock(dev_fd, LOCK_EX | LOCK_NB);
617 		*os_errno = errno;
618 		if (lock_denied) {
619 			if (errno == EAGAIN && tries < max_retry) {
620 				/* <<< debugging
621 				fprintf(stderr,
622 				"\nlibcdio_DEBUG: EAGAIN pass, tries= %d\n",
623 					tries);
624 				*/
625 				usleep(2000000);
626 	continue;
627 			}
628 			sprintf(msg,
629 			    "Device busy. flock(LOCK_EX) failed on %s of %s",
630 			    strlen(lock_name) > 2000 || *pass_dev_no < 0 ?
631 						 "pass device" : lock_name,
632 			    strlen(devname) > 2000 ? "drive" : devname);
633 			return 0;
634 		}
635 	break;
636 	}
637 
638 	/*
639 	fprintf(stderr, "libburn_DEBUG: flock obtained on %s of %s\n",
640 			lock_name, devname);
641 	*/
642 
643 	/* Eventually lock the official device node too */
644 	if (fd_stbuf_valid && name_stbuf_valid &&
645 		(fd_stbuf.st_ino != name_stbuf.st_ino ||
646 		 fd_stbuf.st_dev != name_stbuf.st_dev)) {
647 
648 		*lock_fd = open(devname, O_RDONLY);
649 		if (*lock_fd == 0) {
650 			close(*lock_fd);
651 			*lock_fd = -1;
652 		} if (*lock_fd > 0) {
653 			for (tries = 0; tries <= max_retry; tries++) {
654 				lock_denied =
655 					flock(*lock_fd, LOCK_EX | LOCK_NB);
656 				if (lock_denied) {
657 					if (errno == EAGAIN &&
658 							 tries < max_retry) {
659 						/* <<< debugging
660 						fprintf(stderr,
661 				"\nlibcdio_DEBUG: EAGAIN dev, tries= %d\n",
662 							tries);
663 						*/
664 
665 						usleep(2000000);
666 			continue;
667 					}
668 					close(*lock_fd);
669 					*lock_fd = -1;
670 					sprintf(msg,
671 				 "Device busy. flock(LOCK_EX) failed on %s",
672 				 strlen(devname) > 4000 ? "drive" : devname);
673 					return 0;
674 				}
675 			break;
676 			}
677 		}
678 
679 /*
680 		fprintf(stderr, "libburn_DEBUG: flock obtained on %s\n",
681 				devname);
682 */
683 
684 	}
685 	return 1;
686 }
687 
688 
sg_lock(struct burn_drive * d,int flag)689 static int sg_lock(struct burn_drive *d, int flag)
690 {
691 	int ret, os_errno, pass_dev_no = -1, flock_fd = -1;
692 	char *msg = NULL;
693 
694 	BURN_ALLOC_MEM(msg, char, 4096);
695 	ret = freebsd_dev_lock(d->cam->fd, d->devname,
696 				&os_errno, &pass_dev_no, &flock_fd, msg, 0);
697 	if (ret <= 0) {
698 		libdax_msgs_submit(libdax_messenger, d->global_index,
699 			0x00020008,
700 			LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
701 			msg, os_errno, 0);
702 		sg_close_drive(d);
703 		{ret = 0; goto ex;}
704 	}
705 	if (d->lock_fd > 0)
706 		close(d->lock_fd);
707 	d->lock_fd = flock_fd;
708 	ret = 1;
709 ex:;
710 	BURN_FREE_MEM(msg);
711 	return ret;
712 }
713 
714 
sg_grab(struct burn_drive * d)715 int sg_grab(struct burn_drive *d)
716 {
717 	struct cam_device *cam;
718 	char path_string[80];
719 
720 	if (mmc_function_spy(d, "sg_grab") <= 0)
721 		return 0;
722 
723 	if (burn_drive_is_open(d)) {
724 		d->released = 0;
725 		return 1;
726 	}
727 
728 	cam = cam_open_device(d->devname, O_RDWR);
729 	if (cam == NULL) {
730 		libdax_msgs_submit(libdax_messenger, d->global_index,
731 				0x00020003,
732 				LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
733 				"Could not grab drive", errno, 0);
734 		return 0;
735 	}
736 	d->cam = cam;
737 	if (burn_sg_open_o_excl & 63)
738 		if (sg_lock(d, 0) <= 0)
739 			return 0;
740 	fcntl(cam->fd, F_SETOWN, getpid());
741 
742 	cam_path_string(d->cam, path_string, sizeof(path_string));
743 
744 #ifdef Libburn_ahci_verbouS
745 	fprintf(stderr, "libburn_EXPERIMENTAL: CAM path = %s\n", path_string);
746 #endif
747 
748 	if (strstr(path_string, ":ahcich") != NULL)
749 		d->is_ahci = 1;
750 	else
751 		d->is_ahci = -1;
752 
753 	d->released = 0;
754 	return 1;
755 }
756 
757 
758 /*
759 	non zero return means you still have the drive and it's not
760 	in a state to be released? (is that even possible?)
761 */
762 
sg_release(struct burn_drive * d)763 int sg_release(struct burn_drive *d)
764 {
765 	if (mmc_function_spy(d, "sg_release") <= 0)
766 		return 0;
767 
768 	if (d->cam == NULL)
769 		return 0;
770 
771 	mmc_function_spy(NULL, "sg_release ----------- closing.");
772 
773 	sg_close_drive(d);
774 	d->released = 1;
775 	return 0;
776 }
777 
sg_issue_command(struct burn_drive * d,struct command * c)778 int sg_issue_command(struct burn_drive *d, struct command *c)
779 {
780 	int done = 0, err, sense_len = 0, ret, ignore_error, i;
781 	int cam_pass_err_recover = 0, key, asc, ascq, timeout_ms;
782 	union ccb *ccb;
783 	static FILE *fp = NULL;
784 	time_t start_time;
785 
786 	mmc_function_spy(NULL, "sg_issue_command");
787 
788 	c->error = 0;
789 	memset(c->sense, 0, sizeof(c->sense));
790 
791 	if (d->cam == NULL)
792 		return 0;
793 	if (burn_sg_log_scsi & 1) {
794 		if (fp == NULL) {
795 			fp= fopen("/tmp/libburn_sg_command_log", "a");
796 			fprintf(fp,
797 			    "\n-----------------------------------------\n");
798 		}
799 	}
800 	if (burn_sg_log_scsi & 3)
801 		scsi_log_cmd(c,fp,0);
802 
803 	c->error = 0;
804 	if (c->timeout > 0)
805 		timeout_ms = c->timeout;
806 	else
807 		timeout_ms = 200000;
808 
809 	ccb = cam_getccb(d->cam);
810 	cam_fill_csio(&ccb->csio,
811 				  1,                              /* retries */
812 				  NULL,                           /* cbfncp */
813 				  CAM_DEV_QFRZDIS,                /* flags */
814 				  MSG_SIMPLE_Q_TAG,               /* tag_action */
815 				  NULL,                           /* data_ptr */
816 				  0,                              /* dxfer_len */
817 				  sizeof (ccb->csio.sense_data),  /* sense_len */
818 				  0,                              /* cdb_len */
819 				  timeout_ms);                    /* timeout */
820 	switch (c->dir) {
821 	case TO_DRIVE:
822 		ccb->csio.ccb_h.flags |= CAM_DIR_OUT;
823 		break;
824 	case FROM_DRIVE:
825 		ccb->csio.ccb_h.flags |= CAM_DIR_IN;
826 		break;
827 	case NO_TRANSFER:
828 		ccb->csio.ccb_h.flags |= CAM_DIR_NONE;
829 		break;
830 	}
831 
832 #ifdef Libburn_for_freebsd_ahcI
833 	/* ts B00325 : Advise by Alexander Motin */
834         /* Runs well on 8-STABLE (23 Mar 2003)
835 	   But on 8-RELEASE cam_send_ccb() returns non-zero with errno 6
836            on eject. Long lasting TEST UNIT READY cycles break with
837            errno 16.
838         */
839 #ifdef Libburn_ahci_style_for_alL
840 	{
841 #else
842 	if (d->is_ahci > 0) {
843 #endif
844 		ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
845 		cam_pass_err_recover = 1;
846 	}
847 #endif /* Libburn_for_freebsd_ahcI */
848 
849 	ccb->csio.cdb_len = c->oplen;
850 	memcpy(&ccb->csio.cdb_io.cdb_bytes, &c->opcode, c->oplen);
851 
852 	if (c->page) {
853 		ccb->csio.data_ptr  = c->page->data;
854 		if (c->dir == FROM_DRIVE) {
855 
856 			/* ts A90430 : Ticket 148 , by jwehle :
857 			   "On ... FreeBSD 6.4 which has a usb memory reader in
858 			    addition to a ATAPI DVD burner sg_issue_command
859 			    will hang while the SCSI bus is being scanned"
860 			*/
861 			if (c->dxfer_len >= 0)
862 				ccb->csio.dxfer_len = c->dxfer_len;
863 			else
864 				ccb->csio.dxfer_len = BUFFER_SIZE;
865 
866 /* touch page so we can use valgrind */
867 			memset(c->page->data, 0, BUFFER_SIZE);
868 		} else {
869 			ccb->csio.dxfer_len = c->page->bytes;
870 		}
871 	} else {
872 		ccb->csio.data_ptr  = NULL;
873 		ccb->csio.dxfer_len = 0;
874 	}
875 
876 	/* ts B90523 : Record effective transfer length request for debugging*/
877 	c->dxfer_len = ccb->csio.dxfer_len;
878 
879 	start_time = time(NULL);
880 	for (i = 0; !done; i++) {
881 
882 		memset(&ccb->csio.sense_data, 0, sizeof(ccb->csio.sense_data));
883 		memset(c->sense, 0, sizeof(c->sense));
884 		c->start_time = burn_get_time(0);
885 
886 		err = cam_send_ccb(d->cam, ccb);
887 
888 		c->end_time = burn_get_time(0);
889 		ignore_error = sense_len = 0;
890 		/* ts B00325 : CAM_AUTOSNS_VALID advised by Alexander Motin */
891 		if (ccb->ccb_h.status & CAM_AUTOSNS_VALID) {
892 			/* ts B00110 */
893 			/* Better curb sense_len */
894 			sense_len = ccb->csio.sense_len;
895 			if (sense_len > (int) sizeof(c->sense))
896 				sense_len = sizeof(c->sense);
897 			memcpy(c->sense, &ccb->csio.sense_data, sense_len);
898 			spc_decode_sense(c->sense, sense_len,
899 							&key, &asc, &ascq);
900 			if (sense_len >= 14 && cam_pass_err_recover && key)
901 				ignore_error = 1;
902 		}
903 
904 		if (err == -1 && cam_pass_err_recover && ! ignore_error) {
905 
906 #ifdef Libburn_ahci_verbouS
907 			fprintf(stderr, "libburn_EXPERIMENTAL: errno = %d . cam_errbuf = '%s'\n", errno, cam_errbuf);
908 #endif
909 
910 			if (errno == ENXIO && c->opcode[0] != 0) {
911 				/* Operations on empty or ejected tray */
912 				/* MEDIUM NOT PRESENT */
913 
914 #ifdef Libburn_ahci_verbouS
915 				fprintf(stderr, "libburn_EXPERIMENTAL: Emulating [2,3A,00] MEDIUM NOT PRESENT\n");
916 #endif
917 
918 				c->sense[0] = 0x70; /*Fixed format sense data*/
919 				c->sense[2] = 0x02;
920 				c->sense[12] = 0x3A;
921 				c->sense[13] = 0x00;
922 				sense_len = 14;
923 				ignore_error = 1;
924 			} else if (c->opcode[0] == 0 &&
925 					(errno == EBUSY || errno == ENXIO)) {
926 				/* Timeout of TEST UNIT READY loop */
927 				/* Inquiries while tray is being loaded */
928 				/*LOGICAL UNIT NOT READY,CAUSE NOT REPORTABLE*/
929 
930 #ifdef Libburn_ahci_verbouS
931 				fprintf(stderr, "libburn_EXPERIMENTAL: Emulating [2,04,00] LOGICAL UNIT NOT READY,CAUSE NOT REPORTABLE\n");
932 #endif
933 
934 				c->sense[0] = 0x70; /*Fixed format sense data*/
935 				c->sense[2] = 0x02;
936 				c->sense[12] = 0x04;
937 				c->sense[13] = 0x00;
938 				sense_len = 14;
939 				ignore_error = 1;
940 			} else if (errno == EINVAL) {
941 				/* Inappropriate MODE SENSE */
942 				/* INVALID FIELD IN CDB */
943 
944 #ifdef Libburn_ahci_verbouS
945 				fprintf(stderr, "libburn_EXPERIMENTAL: Emulating [5,24,00] INVALID FIELD IN CDB\n");
946 #endif
947 
948 				c->sense[0] = 0x70; /*Fixed format sense data*/
949 				c->sense[2] = 0x05;
950 				c->sense[12] = 0x24;
951 				c->sense[13] = 0x00;
952 				sense_len = 14;
953 				ignore_error = 1;
954 			}
955 		}
956 
957 		if (err == -1 && !ignore_error) {
958 			libdax_msgs_submit(libdax_messenger,
959 				d->global_index, 0x0002010c,
960 				LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
961 				"Failed to transfer command to drive",
962 				errno, 0);
963 			sg_close_drive(d);
964 			d->released = 1;
965 			d->busy = BURN_DRIVE_IDLE;
966 			c->error = 1;
967 			{ret = -1; goto ex;}
968 		}
969 		/* XXX */
970 
971 		if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
972 			if (sense_len < 14) {
973 				/*LOGICAL UNIT NOT READY,CAUSE NOT REPORTABLE*/
974 
975 #ifdef Libburn_ahci_verbouS
976 				fprintf(stderr, "libburn_EXPERIMENTAL: CAM_STATUS= %d .Emulating [2,04,00] LOGICAL UNIT NOT READY,CAUSE NOT REPORTABLE\n", (ccb->ccb_h.status & CAM_STATUS_MASK));
977 #endif
978 
979 				c->sense[0] = 0x70; /*Fixed format sense data*/
980 				c->sense[2] = 0x02;
981 				c->sense[12] = 0x04;
982 				c->sense[13] = 0x00;
983 				done = 1;
984 			}
985 		}
986 		done = scsi_eval_cmd_outcome(d, c, fp, c->sense,
987 						sense_len, start_time,
988 						timeout_ms, i, !!ignore_error);
989 		if (d->cancel)
990 			done = 1;
991 		if (!done)
992 			spc_register_retry(c);
993 	} while (!done);
994 	ret = 1;
995 ex:;
996 	cam_freeccb(ccb);
997 	return ret;
998 }
999 
1000 
1001 /* ts B00115 */
1002 /* Return 1 if the given path leads to a regular file or a device that can be
1003    fseeked, read and eventually written with 2 kB granularity.
1004 */
1005 int burn_os_is_2k_seekrw(char *path, int flag)
1006 {
1007         struct stat stbuf;
1008 #ifdef Libburn_DIOCGMEDIASIZE_ISBLK
1009 	int fd, ret;
1010 	off_t add_size;
1011 #else
1012 	char *spt;
1013 	int i, e;
1014 #endif /* ! Libburn_DIOCGMEDIASIZE_ISBLK */
1015 
1016         if (stat(path, &stbuf) == -1)
1017                 return 0;
1018         if (S_ISREG(stbuf.st_mode))
1019                 return 1;
1020 	if (!S_ISCHR(stbuf.st_mode))
1021 		return 0;
1022 
1023 #ifdef Libburn_DIOCGMEDIASIZE_ISBLK
1024 
1025 	/* If it throws no error with DIOCGMEDIASIZE then it is a
1026 	   'block device'
1027 	*/
1028 	fd = open(path, O_RDONLY);
1029 	if (fd == -1)
1030 		return 0;
1031 	ret = ioctl(fd, DIOCGMEDIASIZE, &add_size);
1032 	close(fd);
1033 
1034 	return (ret != -1);
1035 
1036 #else /* Libburn_DIOCGMEDIASIZE_ISBLK */
1037 
1038 	spt = strrchr(path, '/');
1039 	if (spt == NULL)
1040 	        spt = path;
1041 	else
1042 	        spt++;
1043 	e = strlen(spt);
1044 	for (i = strlen(spt) - 1; i > 0; i--)
1045 		if (spt[i] >= '0' && spt[i] <= '9')
1046 			e = i;
1047 	if (strncmp(spt, "da", e) == 0) /* SCSI disk. E.g. USB stick. */
1048 		return 1;
1049 	if (strncmp(spt, "cd", e) == 0) /* SCSI CD drive might be writeable. */
1050 		return 1;
1051 	if (strncmp(spt, "ad", e) == 0) /* IDE hard drive */
1052 		return 1;
1053 	if (strncmp(spt, "acd", e) == 0) /* IDE CD drive might be writeable */
1054 		return 1;
1055 	if (strncmp(spt, "fd", e) == 0) /* Floppy disk */
1056 		return 1;
1057 	if (strncmp(spt, "fla", e) == 0) /* Flash drive */
1058 		return 1;
1059 	return 0;
1060 
1061 #endif /* ! Libburn_DIOCGMEDIASIZE_ISBLK */
1062 
1063 }
1064 
1065 
1066 /* ts A70909 */
1067 /** Estimate the potential payload capacity of a file address.
1068     @param path  The address of the file to be examined. If it does not
1069                  exist yet, then the directory will be inquired.
1070     @param bytes This value gets modified if an estimation is possible
1071     @return      -2 = cannot perform necessary operations on file object
1072                  -1 = neither path nor dirname of path exist
1073                   0 = could not estimate size capacity of file object
1074                   1 = estimation has been made, bytes was set
1075 */
1076 int burn_os_stdio_capacity(char *path, off_t write_start, off_t *bytes)
1077 {
1078 	struct stat stbuf;
1079 	struct statvfs vfsbuf;
1080 	char *testpath = NULL, *cpt;
1081 	off_t add_size = 0;
1082 	int fd, ret;
1083 
1084 	BURN_ALLOC_MEM(testpath, char, 4096);
1085 	testpath[0] = 0;
1086 	if (stat(path, &stbuf) == -1) {
1087 		strcpy(testpath, path);
1088 		cpt = strrchr(testpath, '/');
1089 		if(cpt == NULL)
1090 			strcpy(testpath, ".");
1091 		else if(cpt == testpath)
1092 			testpath[1] = 0;
1093 		else
1094 			*cpt = 0;
1095 		if (stat(testpath, &stbuf) == -1)
1096 			{ret = -1; goto ex;}
1097 
1098 #ifdef Libburn_if_this_was_linuX
1099 
1100 	} else if(S_ISBLK(stbuf.st_mode)) {
1101 		int open_mode = O_RDWR, fd, ret;
1102 		long blocks;
1103 
1104 		blocks = *bytes / 512;
1105 		if(burn_sg_open_o_excl)
1106 			open_mode |= O_EXCL;
1107 		fd = open(path, open_mode);
1108 		if (fd == -1)
1109 			{ret = -2; goto ex;}
1110 		ret = ioctl(fd, BLKGETSIZE, &blocks);
1111 		close(fd);
1112 		if (ret == -1)
1113 			{ret = -2; goto ex;}
1114 		*bytes = ((off_t) blocks) * (off_t) 512;
1115 
1116 #endif /* Libburn_if_this_was_linuX */
1117 
1118 
1119 	} else if(S_ISCHR(stbuf.st_mode)) {
1120 		fd = open(path, O_RDONLY);
1121 		if (fd == -1)
1122 			{ret = -2; goto ex;}
1123 		ret = ioctl(fd, DIOCGMEDIASIZE, &add_size);
1124 		close(fd);
1125 		if (ret == -1)
1126 			{ret = -2; goto ex;}
1127 		*bytes = add_size;
1128 	} else if(S_ISREG(stbuf.st_mode)) {
1129 		add_size = burn_sparse_file_addsize(write_start, &stbuf);
1130 		strcpy(testpath, path);
1131 	} else
1132 		{ret = 0; goto ex;}
1133 
1134 	if (testpath[0]) {
1135 		if (statvfs(testpath, &vfsbuf) == -1)
1136 			{ret = -2; goto ex;}
1137 		*bytes = add_size + ((off_t) vfsbuf.f_frsize) *
1138 						(off_t) vfsbuf.f_bavail;
1139 	}
1140 	ret = 1;
1141 ex:
1142 	BURN_FREE_MEM(testpath);
1143 	return ret;
1144 }
1145 
1146 
1147 /* ts A91122 : an interface to open(O_DIRECT) or similar OS tricks. */
1148 
1149 #ifdef Libburn_read_o_direcT
1150 
1151 	/* No special O_DIRECT-like precautions are implemented here */
1152 
1153 #endif /* Libburn_read_o_direcT */
1154 
1155 
1156 int burn_os_open_track_src(char *path, int open_flags, int flag)
1157 {
1158 	int fd;
1159 
1160 	fd = open(path, open_flags);
1161 	return fd;
1162 }
1163 
1164 
1165 void *burn_os_alloc_buffer(size_t amount, int flag)
1166 {
1167 	void *buf = NULL;
1168 
1169 	buf = calloc(1, amount);
1170 	return buf;
1171 }
1172 
1173 
1174 int burn_os_free_buffer(void *buffer, size_t amount, int flag)
1175 {
1176 	if (buffer == NULL)
1177 		return 0;
1178 	free(buffer);
1179 	return 1;
1180 }
1181 
1182