Browse Source

New API calls burn_drive_grab_dummy(), burn_drive_get_drive_role()

ZeroFourZero
Thomas Schmitt 14 years ago
parent
commit
31650eb988
  1. 2
      cdrskin/cdrskin_timestamp.h
  2. 42
      libburn/async.c
  3. 230
      libburn/drive.c
  4. 36
      libburn/libburn.h
  5. 5
      libburn/libdax_msgs.h
  6. 2
      libburn/options.c
  7. 94
      libburn/read.c
  8. 10
      libburn/spc.c
  9. 3
      libburn/transport.h
  10. 240
      libburn/write.c

2
cdrskin/cdrskin_timestamp.h

@ -1 +1 @@
#define Cdrskin_timestamP "2007.09.01.182319"
#define Cdrskin_timestamP "2007.09.04.224905"

42
libburn/async.c

@ -96,7 +96,7 @@ static void add_worker(struct burn_drive *d, WorkerFunc f, void *data)
tmp = workers;
workers = a;
if (d)
if (d != NULL)
d->busy = BURN_DRIVE_SPAWNING;
if (pthread_create(&a->thread, NULL, f, a)) {
@ -211,9 +211,6 @@ void burn_disc_erase(struct burn_drive *drive, int fast)
{
struct erase_opts o;
/* A70103 : will be set to 0 by burn_disc_erase_sync() */
drive->cancel = 1;
/* ts A61006 */
/* a ssert(drive); */
/* a ssert(!SCAN_GOING()); */
@ -233,6 +230,8 @@ void burn_disc_erase(struct burn_drive *drive, int fast)
0, 0);
return;
}
/* A70103 : will be set to 0 by burn_disc_erase_sync() */
drive->cancel = 1;
/* ts A70103 moved up from burn_disc_erase_sync() */
/* ts A60825 : allow on parole to blank appendable CDs */
@ -247,6 +246,8 @@ void burn_disc_erase(struct burn_drive *drive, int fast)
(drive->status != BURN_DISC_FULL &&
drive->status != BURN_DISC_APPENDABLE &&
drive->status != BURN_DISC_BLANK)
||
(drive->drive_role != 1)
) {
libdax_msgs_submit(libdax_messenger, drive->global_index,
0x00020130,
@ -287,6 +288,14 @@ void burn_disc_format(struct burn_drive *drive, off_t size, int flag)
0, 0);
return;
}
if (drive->drive_role != 1) {
libdax_msgs_submit(libdax_messenger, drive->global_index,
0x00020146,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Drive is a virtual placeholder", 0, 0);
drive->cancel = 1;
return;
}
if (flag & 128) /* application prescribed format type */
flag |= 16; /* enforce re-format */
@ -339,13 +348,6 @@ void burn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc)
#endif
/* For the next lines any return indicates failure */
opts->drive->cancel = 1;
/* ts A70203 : people have been warned in API specs */
if (opts->write_type == BURN_WRITE_NONE)
return;
/* ts A61006 */
/* a ssert(!SCAN_GOING()); */
/* a ssert(!find_worker(opts->drive)); */
@ -357,8 +359,24 @@ void burn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc)
0, 0);
return;
}
/* For the next lines any return indicates failure */
opts->drive->cancel = 1;
/* ts A70203 : people have been warned in API specs */
if (opts->write_type == BURN_WRITE_NONE)
return;
if (opts->drive->drive_role == 0) {
libdax_msgs_submit(libdax_messenger, opts->drive->global_index,
0x00020146,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Drive is a virtual placeholder (null-drive)", 0, 0);
return;
}
/* ts A61007 : obsolete Assert in spc_select_write_params() */
if (!opts->drive->mdata->valid) {
if (opts->drive->drive_role == 1 && !opts->drive->mdata->valid) {
libdax_msgs_submit(libdax_messenger,
opts->drive->global_index, 0x00020113,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,

230
libburn/drive.c

@ -35,6 +35,9 @@
/* A70225 : to learn about eventual Libburn_dvd_r_dl_multi_no_close_sessioN */
#include "write.h"
/* A70903 : for burn_scsi_setup_drive() */
#include "spc.h"
#include "libdax_msgs.h"
extern struct libdax_msgs *libdax_messenger;
@ -47,11 +50,30 @@ int burn_setup_drive(struct burn_drive *d, char *fname)
{
d->devname = burn_strdup(fname);
memset(&d->params, 0, sizeof(struct params));
d->idata = NULL;
d->mdata = NULL;
d->toc_entry = NULL;
d->released = 1;
d->status = BURN_DISC_UNREADY;
return 1;
}
/* ts A70903 */
void burn_drive_free_subs(struct burn_drive *d)
{
if (d->idata != NULL)
free((void *) d->idata);
if (d->mdata != NULL) {
burn_mdata_free_subs(d->mdata);
free((void *) d->mdata);
}
if(d->toc_entry != NULL)
free((void *) d->toc_entry);
free(d->devname);
}
/* ts A60904 : ticket 62, contribution by elmom */
/* splitting former burn_drive_free() (which freed all, into two calls) */
void burn_drive_free(struct burn_drive *d)
@ -59,14 +81,10 @@ void burn_drive_free(struct burn_drive *d)
if (d->global_index == -1)
return;
/* ts A60822 : close open fds before forgetting them */
if (burn_drive_is_open(d))
d->release(d);
free((void *) d->idata);
burn_mdata_free_subs(d->mdata);
free((void *) d->mdata);
if(d->toc_entry != NULL)
free((void *) d->toc_entry);
free(d->devname);
if (d->drive_role == 1)
if (burn_drive_is_open(d))
d->release(d);
burn_drive_free_subs(d);
d->global_index = -1;
}
@ -327,6 +345,8 @@ struct burn_drive *burn_drive_finish_enum(struct burn_drive *d)
<<< debug: for tracing calls which might use open drive fds */
int mmc_function_spy(char * text);
d->drive_role = 1; /* MMC drive */
t = burn_drive_register(d);
/* ts A60821 */
@ -399,10 +419,13 @@ void burn_drive_release(struct burn_drive *d, int le)
return;
}
d->unlock(d);
if (le)
d->eject(d);
d->release(d);
if (d->drive_role == 1) {
d->unlock(d);
if (le)
d->eject(d);
d->release(d);
}
d->released = 1;
/* ts A61125 : outsourced model aspects */
@ -485,7 +508,8 @@ void burn_disc_erase_sync(struct burn_drive *d, int fast)
/* ts A61125 : update media state records */
burn_drive_mark_unready(d);
burn_drive_inquire_media(d);
if (d->drive_role == 1)
burn_drive_inquire_media(d);
d->busy = BURN_DRIVE_IDLE;
}
@ -513,6 +537,7 @@ void burn_disc_format_sync(struct burn_drive *d, off_t size, int flag)
stages = 1 + ((flag & 1) && size > 1024 * 1024);
d->cancel = 0;
d->busy = BURN_DRIVE_FORMATTING;
ret = d->format_unit(d, size, flag & 0xff96); /* forward bits */
if (ret <= 0)
d->cancel = 1;
@ -593,6 +618,8 @@ int burn_disc_get_formats(struct burn_drive *d, int *status, off_t *size,
*size = 0;
*bl_sas = 0;
*num_formats = 0;
if (d->drive_role != 1)
return 0;
ret = d->read_format_capacities(d, 0x00);
if (ret <= 0)
return 0;
@ -643,7 +670,7 @@ int burn_disc_erasable(struct burn_drive *d)
enum burn_drive_status burn_drive_get_status(struct burn_drive *d,
struct burn_progress *p)
{
if (p) {
if (p != NULL) {
memcpy(p, &(d->progress), sizeof(struct burn_progress));
/* TODO: add mutex */
}
@ -797,22 +824,6 @@ int burn_drive_scan_sync(struct burn_drive_info *drives[],
return 0;
}
void burn_drive_info_free(struct burn_drive_info drive_infos[])
{
/* ts A60904 : ticket 62, contribution by elmom */
/* clarifying the meaning and the identity of the victim */
/* ts A60904 : This looks a bit weird.
burn_drive_info is not the manager of burn_drive but only its
spokesperson. To my knowlege drive_infos from burn_drive_scan()
are not memorized globally. */
if(drive_infos != NULL)
free((void *) drive_infos);
burn_drive_free_all();
}
/* ts A61001 : internal call */
int burn_drive_forget(struct burn_drive *d, int force)
{
@ -846,6 +857,32 @@ int burn_drive_info_forget(struct burn_drive_info *info, int force)
return burn_drive_forget(info->drive, force);
}
void burn_drive_info_free(struct burn_drive_info drive_infos[])
{
/* ts A60904 : ticket 62, contribution by elmom */
/* clarifying the meaning and the identity of the victim */
/* ts A60904 : This looks a bit weird.
burn_drive_info is not the manager of burn_drive but only its
spokesperson. To my knowlege drive_infos from burn_drive_scan()
are not memorized globally. */
if(drive_infos != NULL)
free((void *) drive_infos);
/* >>> ts A70903 : THIS IS WRONG !
It contradicts the API and endangers multi drive usage.
This call is not entitled to delete all drives, only the
ones of the array.
Problem: it is unclear how many items are listed in drive_infos
Solution: add a dummy element to any burn_drive_info array with
drive == NULL
*/
burn_drive_free_all();
}
struct burn_disc *burn_drive_get_disc(struct burn_drive *d)
{
/* ts A61022: SIGSEGV on calling this function with blank media */
@ -858,6 +895,9 @@ struct burn_disc *burn_drive_get_disc(struct burn_drive *d)
void burn_drive_set_speed(struct burn_drive *d, int r, int w)
{
d->nominal_write_speed = w;
if(d->drive_role != 1)
return;
d->set_speed(d, r, w);
}
@ -904,17 +944,23 @@ void burn_sectors_to_msf(int sectors, int *m, int *s, int *f)
int burn_drive_get_read_speed(struct burn_drive *d)
{
if(!d->mdata->valid)
return 0;
return d->mdata->max_read_speed;
}
int burn_drive_get_write_speed(struct burn_drive *d)
{
if(!d->mdata->valid)
return 0;
return d->mdata->max_write_speed;
}
/* ts A61021 : New API function */
int burn_drive_get_min_write_speed(struct burn_drive *d)
{
if(!d->mdata->valid)
return 0;
return d->mdata->min_write_speed;
}
@ -1383,6 +1429,8 @@ int burn_drive_get_start_end_lba(struct burn_drive *d,
/* ts A61020 API function */
int burn_disc_pretend_blank(struct burn_drive *d)
{
if (d->drive_role == 0)
return 0;
if (d->status != BURN_DISC_UNREADY &&
d->status != BURN_DISC_UNSUITABLE)
return 0;
@ -1393,6 +1441,8 @@ int burn_disc_pretend_blank(struct burn_drive *d)
/* ts A61106 API function */
int burn_disc_pretend_full(struct burn_drive *d)
{
if (d->drive_role == 0)
return 0;
if (d->status != BURN_DISC_UNREADY &&
d->status != BURN_DISC_UNSUITABLE)
return 0;
@ -1411,6 +1461,8 @@ int burn_disc_read_atip(struct burn_drive *d)
0, 0);
return -1;
}
if(d->drive_role != 1)
return 0;
if (d->current_profile == -1 || d->current_is_cd_profile) {
d->read_atip(d);
/* >>> some control of success would be nice :) */
@ -1443,6 +1495,9 @@ int burn_disc_track_lba_nwa(struct burn_drive *d, struct burn_write_opts *o,
0, 0);
return -1;
}
*lba = *nwa = 0;
if (d->drive_role != 1)
return 0;
if (o != NULL)
d->send_write_parameters(d, o);
ret = d->get_nwa(d, trackno, lba, nwa);
@ -1471,6 +1526,9 @@ int burn_disc_get_msc1(struct burn_drive *d, int *start)
0, 0);
return -1;
}
*start = 0;
if (d->drive_role != 1)
return 0;
ret = d->read_multi_session_c1(d, &trackno, start);
return ret;
}
@ -1483,13 +1541,20 @@ off_t burn_disc_available_space(struct burn_drive *d,
int lba, nwa;
if (burn_drive_is_released(d))
goto ex;
return 0;
if (d->busy != BURN_DRIVE_IDLE)
goto ex;
return 0;
if (d->drive_role == 0)
return 0;
if (d->drive_role == 2) {
/* >>> how to estimate available space for a stdio file ? */
return ((off_t) (1024 * 1024 * 1024) * (off_t) 2048);
}
if (o != NULL)
d->send_write_parameters(d, o);
d->get_nwa(d, -1, &lba, &nwa);
ex:;
if (o != NULL) {
if (o->start_byte > 0) {
if (o->start_byte > d->media_capacity_remaining)
@ -1594,6 +1659,8 @@ int burn_speed_descriptor_copy(struct burn_speed_descriptor *from,
/* ts A61226 : free dynamically allocated sub data of struct scsi_mode_data */
int burn_mdata_free_subs(struct scsi_mode_data *m)
{
if(!m->valid)
return 0;
burn_speed_descriptor_destroy(&(m->speed_descriptors), 1);
return 1;
}
@ -1607,6 +1674,8 @@ int burn_drive_get_speedlist(struct burn_drive *d,
struct burn_speed_descriptor *sd, *csd = NULL;
(*speed_list) = NULL;
if(!d->mdata->valid)
return 0;
for (sd = d->mdata->speed_descriptors; sd != NULL; sd = sd->next) {
ret = burn_speed_descriptor_new(&csd, NULL, csd, 0);
if (ret <= 0)
@ -1630,6 +1699,8 @@ int burn_drive_get_best_speed(struct burn_drive *d, int speed_goal,
if (speed_goal < 0)
best_speed = 2000000000;
*best_descr = NULL;
if(!d->mdata->valid)
return 0;
for (sd = d->mdata->speed_descriptors; sd != NULL; sd = sd->next) {
if (flag & 1)
speed = sd->read_speed;
@ -1703,7 +1774,21 @@ int burn_disc_get_multi_caps(struct burn_drive *d, enum burn_write_types wt,
o->current_is_cd_profile = d->current_is_cd_profile;
o->might_simulate = 0;
if (s != BURN_DISC_BLANK && s != BURN_DISC_APPENDABLE) {
if (d->drive_role == 0)
return 0;
if (d->drive_role == 2) {
/* stdio file dummy drive */
o->start_adr = 1;
size = ((off_t) (1024 * 1024 * 1024) * (off_t) 2048);
/* >>> obtain realistic file size */
o->start_range_high = size;
o->start_alignment = 2048; /* imposting a drive, not a file */
o->might_do_sao = 4;
o->might_do_tao = 2;
o->advised_write_mode = BURN_WRITE_TAO;
} else if (s != BURN_DISC_BLANK && s != BURN_DISC_APPENDABLE) {
return 0;
} else if (s == BURN_DISC_APPENDABLE &&
(wt == BURN_WRITE_SAO || wt == BURN_WRITE_RAW)) {
@ -1880,3 +1965,80 @@ int burn_disc_get_write_mode_demands(struct burn_disc *disc,
}
return (disc->sessions > 0);
}
/* ts A70903 : API */
int burn_drive_grab_dummy(struct burn_drive_info *drive_infos[], char *fname)
{
int ret;
struct burn_drive *d= NULL, *regd_d;
struct stat stbuf;
if (fname[0] != 0) {
if (stat(fname, &stbuf) == -1) {
/* >>> ? reject ? try to create ? */;
} else if(S_ISREG(stbuf.st_mode) || S_ISBLK(stbuf.st_mode)) {
/* >>> ? open for a test ? */;
} else {
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020149,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Unsuitable filetype for pseudo-drive", 0, 0);
return 0;
}
}
d= (struct burn_drive *) calloc(1, sizeof(struct burn_drive));
if (d == NULL)
return 0;
d->status = BURN_DISC_EMPTY;
burn_setup_drive(d, fname);
if (fname[0] != 0)
d->drive_role = 2;
else
d->drive_role = 0;
ret = burn_scsi_setup_drive(d, -1, -1, -1, -1, -1, 0);
if (ret <= 0)
goto ex;
regd_d = burn_drive_register(d);
if (regd_d == NULL) {
ret = -1;
goto ex;
}
if (d->drive_role == 2) {
d->status = BURN_DISC_BLANK;
d->current_profile = 0; /* MMC reserved */
strcpy(d->current_profile_text,"stdio file");
d->current_is_cd_profile = 0;
d->current_is_supported_profile = 1;
d->block_types[BURN_WRITE_TAO] = BURN_BLOCK_MODE1;
d->block_types[BURN_WRITE_SAO] = BURN_BLOCK_MODE1;
}
*drive_infos = calloc(2, sizeof(struct burn_drive_info));
if (*drive_infos == NULL)
goto ex;
(*drive_infos)[0].drive = d;
(*drive_infos)[1].drive = NULL; /* End-Of-List mark */
(*drive_infos)[0].tao_block_types = d->block_types[BURN_WRITE_TAO];
(*drive_infos)[0].sao_block_types = d->block_types[BURN_WRITE_SAO];
d->released = 0;
ret = 1;
ex:;
if (ret <= 0 && d != NULL) {
burn_drive_free_subs(d);
free((char *) d);
}
return ret;
}
/* ts A70903 : API */
int burn_drive_get_drive_role(struct burn_drive *d)
{
return d->drive_role;
}

36
libburn/libburn.h

@ -1302,7 +1302,7 @@ struct burn_source *burn_fd_source_new(int datafd, int subfd, off_t size);
/* ts A70328 */
/** Sets a fixed track size after the data source object has already been
created.
@param t The track to poperate on
@param t The track to operate on
@param size the number of bytes to use as track size
@return <=0 indicates failure , >0 success
*/
@ -1901,6 +1901,40 @@ int burn_read_data(struct burn_drive *d, off_t byte_address,
char data[], off_t data_size, off_t *data_count, int flag);
/* ts A70903 */
/** Create and aquire a pseudo-drive which will accept option settings much
like a MMC burner drive. Many of them will not cause any effect, though.
There are two kinds of pseudo-drives: stdio-drives and null-drives.
A stdio-drive performs all its eventual data transfer activities on a file
via standard i/o functions open(2), lseek(2), read(2), write(2), close(2).
Its capabilities resemble DVD-RAM but the media profile reported is 0x00
and it issues no realistic write space information.
A null-drive is created if the parameter "name" is an empty string. It will
pretend to have loaded no media.
@param drive_infos On success returns a one element array with the drive
(cdrom/burner). Thus use with driveno 0 only. On failure
the array has no valid elements at all.
The returned array should be freed via burn_drive_info_free()
when it is no longer needed.
@param name Sets the file address to be used for writing. Permissible
file types are regular file or block device. If the file
does not exist, it is attempted to create it as regular file.
An empty fname creates a null-drive.
@return 1 success , <=0 failure
*/
int burn_drive_grab_dummy(struct burn_drive_info *drive_infos[], char *fname);
/** Inquire wether the drive object is a real MMC drive or a pseudo-drive
created by burn_drive_dummy().
@param d The drive to inquire
@return 0= null-drive
1= real MMC drive
2= stdio-drive
*/
int burn_drive_get_drive_role(struct burn_drive *d);
#ifndef DOXYGEN
BURN_END_DECLS

5
libburn/libdax_msgs.h

@ -377,6 +377,11 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
0x00020143 (SORRY,HIGH) = Read start address not properly aligned
0x00020144 (SORRY,HIGH) = SCSI error on read
0x00020145 (FATAL,HIGH) = Drive is busy on attempt to read data
0x00020146 (FATAL,HIGH) = Drive is a virtual placeholder
0x00020147 (SORRY,HIGH) = Cannot address start byte
0x00020148 (SORRY,HIGH) = Cannot write desired amount of data
0x00020149 (SORRY,HIGH) = Unsuitable filetype for pseudo-drive
0x0002014a (SORRY,HIGH) = Cannot read desired amount of data
libdax_audioxtr:

2
libburn/options.c

@ -142,6 +142,8 @@ int burn_write_opts_set_simulate(struct burn_write_opts *opts, int sim)
int burn_write_opts_set_underrun_proof(struct burn_write_opts *opts,
int underrun_proof)
{
if (!opts->drive->mdata->valid)
return 0;
if (opts->drive->mdata->underrun_proof) {
opts->underrun_proof = underrun_proof;
return 1;

94
libburn/read.c

@ -12,6 +12,9 @@
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#include <errno.h>
#include "sector.h"
#include "libburn.h"
#include "drive.h"
@ -288,12 +291,37 @@ static void flipq(unsigned char *sub)
*/
/* ts A70904 */
/** @param flag bit=be silent on data shortage */
int burn_stdio_read(int fd, char *buf, int bufsize, struct burn_drive *d,
int flag)
{
int todo, count = 0;
for(todo = bufsize; todo > 0; ) {
count = read(fd, buf + (bufsize - todo), todo);
if(count <= 0)
break;
todo -= count;
}
if(todo > 0 && !(flag & 1)) {
libdax_msgs_submit(libdax_messenger, d->global_index,
0x0002014a,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Cannot read desired amount of data", errno, 0);
}
if (count < 0)
return -1;
return (bufsize - todo);
}
/* ts A70812 : API function */
int burn_read_data(struct burn_drive *d, off_t byte_address,
char data[], off_t data_size, off_t *data_count, int flag)
{
int alignment = 2048, start, upto, chunksize = 1, err, cpy_size, i;
int sose_mem = 0;
int sose_mem = 0, fd = -1, ret;
char msg[81], *wpt;
struct buffer buf;
@ -307,6 +335,13 @@ int burn_read_data(struct burn_drive *d, off_t byte_address,
"Drive is not grabbed on random access write", 0, 0);
return 0;
}
if (d->drive_role == 0) {
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020146,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Drive is a virtual placeholder (null-drive)", 0, 0);
return 0;
}
if ((byte_address % alignment) != 0) {
sprintf(msg,
"Read start address not properly aligned (%d bytes)",
@ -325,6 +360,33 @@ int burn_read_data(struct burn_drive *d, off_t byte_address,
"Drive is busy on attempt to read data", 0, 0);
return 0;
}
if (d->drive_role != 1) {
/* <<< We need _LARGEFILE64_SOURCE defined by the build system.
*/
#ifndef O_LARGEFILE
#define O_LARGEFILE 0
#endif
fd = open(d->devname, O_RDONLY | O_LARGEFILE);
if (fd == -1) {
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020005,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Failed to open device (a pseudo-drive)",
errno, 0);
ret = 0; goto ex;
}
if (lseek(fd, byte_address, SEEK_SET) == -1) {
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020147,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Cannot address start byte", errno, 0);
ret = 0; goto ex;
}
}
d->busy = BURN_DRIVE_READING_SYNC;
d->buffer = &buf;
@ -342,7 +404,14 @@ int burn_read_data(struct burn_drive *d, off_t byte_address,
cpy_size = data_size - *data_count;
if (flag & 2)
d->silent_on_scsi_error = 1;
err = d->read_10(d, start, chunksize, d->buffer);
if (d->drive_role == 1) {
err = d->read_10(d, start, chunksize, d->buffer);
} else {
ret = burn_stdio_read(fd, (char *) d->buffer->data,
cpy_size, d, 0);
if (ret <= 0)
err = BE_CANCELLED;
}
if (flag & 2)
d->silent_on_scsi_error = sose_mem;
if (err == BE_CANCELLED) {
@ -350,7 +419,16 @@ int burn_read_data(struct burn_drive *d, off_t byte_address,
for (i = 0; i < chunksize - 1; i++) {
if (flag & 2)
d->silent_on_scsi_error = 1;
err = d->read_10(d, start + i, 1, d->buffer);
if (d->drive_role == 1) {
err = d->read_10(d, start + i, 1,
d->buffer);
} else {
ret = burn_stdio_read(fd,
(char *) d->buffer->data,
2048, d, 1);
if (ret <= 0)
err = BE_CANCELLED;
}
if (flag & 2)
d->silent_on_scsi_error = sose_mem;
if (err == BE_CANCELLED)
@ -359,16 +437,18 @@ int burn_read_data(struct burn_drive *d, off_t byte_address,
wpt += 2048;
*data_count += 2048;
}
d->buffer = NULL;
d->busy = BURN_DRIVE_IDLE;
return 0;
ret = 0; goto ex;
}
memcpy(wpt, d->buffer->data, cpy_size);
wpt += cpy_size;
*data_count += cpy_size;
}
ret = 1;
ex:;
if (fd != -1)
close(fd);
d->buffer = NULL;
d->busy = BURN_DRIVE_IDLE;
return 1;
return ret;
}

10
libburn/spc.c

@ -739,11 +739,8 @@ int burn_scsi_setup_drive(struct burn_drive *d, int bus_no, int host_no,
d->silent_on_scsi_error = 0;
d->idata = malloc(sizeof(struct burn_scsi_inquiry_data));
d->idata->valid = 0;
d->mdata = malloc(sizeof(struct scsi_mode_data));
d->mdata->valid = 0;
d->mdata->speed_descriptors = NULL;
d->idata = calloc(1, sizeof(struct burn_scsi_inquiry_data));
d->mdata = calloc(1, sizeof(struct scsi_mode_data));
/* ts A61007 : obsolete Assert in drive_getcaps() */
if(d->idata == NULL || d->mdata == NULL) {
@ -752,6 +749,9 @@ int burn_scsi_setup_drive(struct burn_drive *d, int bus_no, int host_no,
"Could not allocate new drive object", 0, 0);
return -1;
}
d->idata->valid = 0;
d->mdata->valid = 0;
d->mdata->speed_descriptors = NULL;
if(!(flag & 1)) {
ret = spc_setup_drive(d);
if (ret<=0)

3
libburn/transport.h

@ -121,6 +121,9 @@ struct burn_format_descr {
/** Gets initialized in enumerate_common() and burn_drive_register() */
struct burn_drive
{
/* ts A70902: 0=null-emulation , 1=MMC drive , 2=stdio-emulation */
int drive_role;
int bus_no;
int host;
int id;

240
libburn/write.c

@ -18,11 +18,15 @@
#define Libburn_sao_can_appenD 1
*/
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>
#include "error.h"
#include "sector.h"
#include "libburn.h"
@ -910,6 +914,13 @@ int burn_precheck_write(struct burn_write_opts *o, struct burn_disc *disc,
reason_pt= reasons;
reasons[0] = 0;
if (d->drive_role == 0) {
sprintf(reasons,
"DRIVE: is a virtual placeholder (null-drive)");
no_media = 1;
goto ex;
}
/* check write mode against write job */
wt = burn_write_opts_auto_write_type(o, disc, reasons, 1);
if (wt == BURN_WRITE_NONE) {
@ -922,16 +933,18 @@ int burn_precheck_write(struct burn_write_opts *o, struct burn_disc *disc,
reason_pt= reasons + strlen(reasons);
if (d->status == BURN_DISC_UNSUITABLE)
goto unsuitable_profile;
if (d->current_profile == 0x09 || d->current_profile == 0x0a) {
if (d->drive_role == 2 ||
d->current_profile == 0x1a || d->current_profile == 0x12) {
/* DVD+RW , DVD-RAM , emulated drive on stdio file */
if (o->start_byte >= 0 && (o->start_byte % 2048))
strcat(reasons,
"write start address not properly aligned to 2048, ");
} else if (d->current_profile == 0x09 || d->current_profile == 0x0a) {
/* CD-R , CD-RW */
if (!burn_disc_write_is_ok(o, disc, (!!silent) << 1))
strcat(reasons, "unsuitable track mode found, ");
if (o->start_byte >= 0)
strcat(reasons, "write start address not supported, ");
} else if (d->current_profile == 0x1a || d->current_profile == 0x12) {
/* DVD+RW , DVD-RAM */
if (o->start_byte >= 0 && (o->start_byte % 2048))
strcat(reasons,
"write start address not properly aligned to 2048, ");
} else if (d->current_profile == 0x13) {
/* DVD-RW Restricted Overwrite */
if (o->start_byte >= 0 && (o->start_byte % 32768))
@ -1431,8 +1444,6 @@ int burn_disc_setup_dvd_minus_rw(struct burn_write_opts *o,
/* >>> perform OPC if needed */;
/* >>> */;
return 1;
}
@ -1743,6 +1754,177 @@ early_failure:;
}
/* ts A70904 */
int burn_stdio_open_write(struct burn_drive *d, off_t start_byte, int flag)
{
int fd = -1;
int mode = O_RDWR | O_CREAT;
char msg[160];
/* <<< We need _LARGEFILE64_SOURCE defined by the build system.
*/
#ifndef O_LARGEFILE
#define O_LARGEFILE 0
#endif
if (d->devname[0] == 0) /* null drives should not come here */
return -1;
fd = open(d->devname, mode, S_IRUSR | S_IWUSR);
if (fd == -1) {
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020005,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Failed to open device (a pseudo-drive)", errno, 0);
}
if (start_byte < 0)
start_byte = 0;
if (lseek(fd, start_byte, SEEK_SET)==-1) {
sprintf(msg, "Cannot address start byte %.f",
(double) start_byte);
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020147,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
msg, errno, 0);
close(fd);
fd = -1;
}
d->nwa = start_byte / 2048;
return fd;
}
/* ts A70904 */
int burn_stdio_read_source(struct burn_source *source, char *buf, int bufsize,
struct burn_write_opts *o, int flag)
{
int count= 0, todo;
for(todo = bufsize; todo > 0; todo -= count) {
count = source->read(source,
(unsigned char *) (buf + (bufsize - todo)), todo);
if (count <= 0)
break;
}
return (bufsize - todo);
}
/* ts A70904 */
int burn_stdio_write(int fd, char *buf, int count, struct burn_drive *d,
int flag)
{
if (write(fd, buf, count) != count) {
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020148,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Cannot write desired amount of data", errno, 0);
return 0;
}
return count;
}
/* ts A70904 */
int burn_stdio_write_track(struct burn_write_opts *o, struct burn_session *s,
int tnum, int fd, int flag)
{
int open_ended, bufsize, ret, eof_seen = 0, sectors;
struct burn_track *t = s->track[tnum];
struct burn_drive *d = o->drive;
off_t t_size, w_count;
char buf[16*2048];
bufsize = sizeof(buf);
sectors = burn_track_get_sectors(t);
burn_disc_init_track_status(o, s, tnum, sectors);
/* >>> write t->offset zeros */;
open_ended = burn_track_is_open_ended(t);
t_size = t->source->get_size(t->source);
for(w_count = 0; w_count < t_size || open_ended; w_count += ret) {
if (t_size - w_count < bufsize && ! open_ended)
/* >>> what about final sector padding ? */
bufsize = t_size - w_count;
if (eof_seen)
ret = 0;
else
ret = burn_stdio_read_source(t->source, buf,
bufsize, o, 0);
if (ret < 0)
return ret;
if (ret == 0 && open_ended)
break;
if (ret < bufsize && !open_ended) {
memset(buf + ret, 0, bufsize - ret);
eof_seen = 1;
ret = bufsize;
}
ret = burn_stdio_write(fd, buf, ret, d, 0);
if (ret <= 0)
return ret;
d->progress.sector = (w_count + (off_t) ret) / (off_t) 2048;
if (open_ended)
d->progress.sectors = d->progress.sector;
}
/* >>> write t->tail zeros */;
return 1;
}
/* ts A70904 */
int burn_stdio_write_sync(struct burn_write_opts *o,
struct burn_disc *disc)
{
int ret, fd = -1;
struct burn_drive *d = o->drive;
d->needs_close_session = 0;
o->obs_pad = 0; /* no filling-up of track's last 32k buffer */
o->obs = 32*1024; /* buffer size */
if (disc->sessions != 1)
{ret= 0 ; goto ex;}
if (disc->session[0]->tracks != 1)
{ret= 0 ; goto ex;}
/* update progress */
d->progress.session = 0;
d->progress.tracks = 1;
/* open target file */
fd = burn_stdio_open_write(d, o->start_byte, 0);
if (fd == -1)
{ret = 0; goto ex;}
ret = burn_stdio_write_track(o, disc->session[0], 0, fd, 0);
if (ret <= 0)
goto ex;
/* XXX: currently signs an end of session */
d->progress.sector = 0;
d->progress.start_sector = 0;
d->progress.sectors = 0;
ret = 1;
ex:;
if (fd != -1)
close (fd);
/* update media state records */
burn_drive_mark_unready(d);
d->busy = BURN_DRIVE_IDLE;
return ret;
}
void burn_disc_write_sync(struct burn_write_opts *o, struct burn_disc *disc)
{
struct cue_sheet *sheet;
@ -1765,6 +1947,13 @@ void burn_disc_write_sync(struct burn_write_opts *o, struct burn_disc *disc)
d->rlba = -150;
d->toc_temp = 9;
/* ts A70904 */
if (d->drive_role != 1) {
ret = burn_stdio_write_sync(o, disc);
if (ret <= 0)
goto fail_wo_sync;
return;
}
/* ts A61218 */
if (! d->current_is_cd_profile) {
ret = burn_dvd_write_sync(o, disc);
@ -1974,7 +2163,7 @@ fail_wo_sync:;
int burn_random_access_write(struct burn_drive *d, off_t byte_address,
char *data, off_t data_count, int flag)
{
int alignment = 0, start, upto, chunksize, err;
int alignment = 0, start, upto, chunksize, err, fd = -1, ret;
char msg[81], *rpt;
struct buffer buf;
@ -1985,6 +2174,16 @@ int burn_random_access_write(struct burn_drive *d, off_t byte_address,
"Drive is not grabbed on random access write", 0, 0);
return 0;
}
if(d->drive_role == 0) {
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020146,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Drive is a virtual placeholder (null-drive)", 0, 0);
return 0;
}
if(d->drive_role != 1)
alignment = 2 * 1024;
if (d->current_profile == 0x12) /* DVD-RAM */
alignment = 2 * 1024;
if (d->current_profile == 0x13) /* DVD-RW restricted overwrite */
@ -2019,7 +2218,6 @@ int burn_random_access_write(struct burn_drive *d, off_t byte_address,
msg, 0, 0);
return 0;
}
if (d->busy != BURN_DRIVE_IDLE) {
libdax_msgs_submit(libdax_messenger,
d->global_index, 0x00020140,
@ -2027,6 +2225,11 @@ int burn_random_access_write(struct burn_drive *d, off_t byte_address,
"Drive is busy on attempt to write random access",0,0);
return 0;
}
if(d->drive_role != 1) {
fd = burn_stdio_open_write(d, byte_address, 0);
if (fd == -1)
return 0;
}
d->busy = BURN_DRIVE_WRITING_SYNC;
d->buffer = &buf;
@ -2042,15 +2245,26 @@ int burn_random_access_write(struct burn_drive *d, off_t byte_address,
rpt += d->buffer->bytes;
d->buffer->sectors = chunksize;
d->nwa = start;
err = d->write(d, d->nwa, d->buffer);
if(d->drive_role == 1) {
err = d->write(d, d->nwa, d->buffer);
} else {
ret = burn_stdio_write(fd, (char *) d->buffer->data,
d->buffer->bytes, d, 0);
if (ret <= 0)
err = BE_CANCELLED;
}
if (err == BE_CANCELLED) {
d->busy = BURN_DRIVE_IDLE;
if(fd != -1)
close(fd);
return (-(start * 2048 - byte_address));
}
}
if (flag & 1)
if(d->drive_role == 1 && (flag & 1))
d->sync_cache(d);
if(fd != -1)
close(fd);
d->buffer = NULL;
d->busy = BURN_DRIVE_IDLE;
return 1;

Loading…
Cancel
Save