New API calls burn_drive_grab_dummy(), burn_drive_get_drive_role()

This commit is contained in:
Thomas Schmitt 2007-09-04 22:50:04 +00:00
parent 797f403b0d
commit 31650eb988
10 changed files with 591 additions and 73 deletions

View File

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

View File

@ -96,7 +96,7 @@ static void add_worker(struct burn_drive *d, WorkerFunc f, void *data)
tmp = workers; tmp = workers;
workers = a; workers = a;
if (d) if (d != NULL)
d->busy = BURN_DRIVE_SPAWNING; d->busy = BURN_DRIVE_SPAWNING;
if (pthread_create(&a->thread, NULL, f, a)) { 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; struct erase_opts o;
/* A70103 : will be set to 0 by burn_disc_erase_sync() */
drive->cancel = 1;
/* ts A61006 */ /* ts A61006 */
/* a ssert(drive); */ /* a ssert(drive); */
/* a ssert(!SCAN_GOING()); */ /* a ssert(!SCAN_GOING()); */
@ -233,6 +230,8 @@ void burn_disc_erase(struct burn_drive *drive, int fast)
0, 0); 0, 0);
return; 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 A70103 moved up from burn_disc_erase_sync() */
/* ts A60825 : allow on parole to blank appendable CDs */ /* 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_FULL &&
drive->status != BURN_DISC_APPENDABLE && drive->status != BURN_DISC_APPENDABLE &&
drive->status != BURN_DISC_BLANK) drive->status != BURN_DISC_BLANK)
||
(drive->drive_role != 1)
) { ) {
libdax_msgs_submit(libdax_messenger, drive->global_index, libdax_msgs_submit(libdax_messenger, drive->global_index,
0x00020130, 0x00020130,
@ -287,6 +288,14 @@ void burn_disc_format(struct burn_drive *drive, off_t size, int flag)
0, 0); 0, 0);
return; 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 */ if (flag & 128) /* application prescribed format type */
flag |= 16; /* enforce re-format */ flag |= 16; /* enforce re-format */
@ -339,13 +348,6 @@ void burn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc)
#endif #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 */ /* ts A61006 */
/* a ssert(!SCAN_GOING()); */ /* a ssert(!SCAN_GOING()); */
/* a ssert(!find_worker(opts->drive)); */ /* 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); 0, 0);
return; 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() */ /* 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, libdax_msgs_submit(libdax_messenger,
opts->drive->global_index, 0x00020113, opts->drive->global_index, 0x00020113,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,

View File

@ -35,6 +35,9 @@
/* A70225 : to learn about eventual Libburn_dvd_r_dl_multi_no_close_sessioN */ /* A70225 : to learn about eventual Libburn_dvd_r_dl_multi_no_close_sessioN */
#include "write.h" #include "write.h"
/* A70903 : for burn_scsi_setup_drive() */
#include "spc.h"
#include "libdax_msgs.h" #include "libdax_msgs.h"
extern struct libdax_msgs *libdax_messenger; 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); d->devname = burn_strdup(fname);
memset(&d->params, 0, sizeof(struct params)); memset(&d->params, 0, sizeof(struct params));
d->idata = NULL;
d->mdata = NULL;
d->toc_entry = NULL;
d->released = 1; d->released = 1;
d->status = BURN_DISC_UNREADY; d->status = BURN_DISC_UNREADY;
return 1; 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 */ /* ts A60904 : ticket 62, contribution by elmom */
/* splitting former burn_drive_free() (which freed all, into two calls) */ /* splitting former burn_drive_free() (which freed all, into two calls) */
void burn_drive_free(struct burn_drive *d) 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) if (d->global_index == -1)
return; return;
/* ts A60822 : close open fds before forgetting them */ /* ts A60822 : close open fds before forgetting them */
if (burn_drive_is_open(d)) if (d->drive_role == 1)
d->release(d); if (burn_drive_is_open(d))
free((void *) d->idata); d->release(d);
burn_mdata_free_subs(d->mdata); burn_drive_free_subs(d);
free((void *) d->mdata);
if(d->toc_entry != NULL)
free((void *) d->toc_entry);
free(d->devname);
d->global_index = -1; 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 */ <<< debug: for tracing calls which might use open drive fds */
int mmc_function_spy(char * text); int mmc_function_spy(char * text);
d->drive_role = 1; /* MMC drive */
t = burn_drive_register(d); t = burn_drive_register(d);
/* ts A60821 */ /* ts A60821 */
@ -399,10 +419,13 @@ void burn_drive_release(struct burn_drive *d, int le)
return; return;
} }
d->unlock(d); if (d->drive_role == 1) {
if (le) d->unlock(d);
d->eject(d); if (le)
d->release(d); d->eject(d);
d->release(d);
}
d->released = 1; d->released = 1;
/* ts A61125 : outsourced model aspects */ /* 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 */ /* ts A61125 : update media state records */
burn_drive_mark_unready(d); 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; 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); stages = 1 + ((flag & 1) && size > 1024 * 1024);
d->cancel = 0; d->cancel = 0;
d->busy = BURN_DRIVE_FORMATTING; d->busy = BURN_DRIVE_FORMATTING;
ret = d->format_unit(d, size, flag & 0xff96); /* forward bits */ ret = d->format_unit(d, size, flag & 0xff96); /* forward bits */
if (ret <= 0) if (ret <= 0)
d->cancel = 1; d->cancel = 1;
@ -593,6 +618,8 @@ int burn_disc_get_formats(struct burn_drive *d, int *status, off_t *size,
*size = 0; *size = 0;
*bl_sas = 0; *bl_sas = 0;
*num_formats = 0; *num_formats = 0;
if (d->drive_role != 1)
return 0;
ret = d->read_format_capacities(d, 0x00); ret = d->read_format_capacities(d, 0x00);
if (ret <= 0) if (ret <= 0)
return 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, enum burn_drive_status burn_drive_get_status(struct burn_drive *d,
struct burn_progress *p) struct burn_progress *p)
{ {
if (p) { if (p != NULL) {
memcpy(p, &(d->progress), sizeof(struct burn_progress)); memcpy(p, &(d->progress), sizeof(struct burn_progress));
/* TODO: add mutex */ /* TODO: add mutex */
} }
@ -797,22 +824,6 @@ int burn_drive_scan_sync(struct burn_drive_info *drives[],
return 0; 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 */ /* ts A61001 : internal call */
int burn_drive_forget(struct burn_drive *d, int force) 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); 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) struct burn_disc *burn_drive_get_disc(struct burn_drive *d)
{ {
/* ts A61022: SIGSEGV on calling this function with blank media */ /* 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) 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); 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) int burn_drive_get_read_speed(struct burn_drive *d)
{ {
if(!d->mdata->valid)
return 0;
return d->mdata->max_read_speed; return d->mdata->max_read_speed;
} }
int burn_drive_get_write_speed(struct burn_drive *d) int burn_drive_get_write_speed(struct burn_drive *d)
{ {
if(!d->mdata->valid)
return 0;
return d->mdata->max_write_speed; return d->mdata->max_write_speed;
} }
/* ts A61021 : New API function */ /* ts A61021 : New API function */
int burn_drive_get_min_write_speed(struct burn_drive *d) int burn_drive_get_min_write_speed(struct burn_drive *d)
{ {
if(!d->mdata->valid)
return 0;
return d->mdata->min_write_speed; 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 */ /* ts A61020 API function */
int burn_disc_pretend_blank(struct burn_drive *d) int burn_disc_pretend_blank(struct burn_drive *d)
{ {
if (d->drive_role == 0)
return 0;
if (d->status != BURN_DISC_UNREADY && if (d->status != BURN_DISC_UNREADY &&
d->status != BURN_DISC_UNSUITABLE) d->status != BURN_DISC_UNSUITABLE)
return 0; return 0;
@ -1393,6 +1441,8 @@ int burn_disc_pretend_blank(struct burn_drive *d)
/* ts A61106 API function */ /* ts A61106 API function */
int burn_disc_pretend_full(struct burn_drive *d) int burn_disc_pretend_full(struct burn_drive *d)
{ {
if (d->drive_role == 0)
return 0;
if (d->status != BURN_DISC_UNREADY && if (d->status != BURN_DISC_UNREADY &&
d->status != BURN_DISC_UNSUITABLE) d->status != BURN_DISC_UNSUITABLE)
return 0; return 0;
@ -1411,6 +1461,8 @@ int burn_disc_read_atip(struct burn_drive *d)
0, 0); 0, 0);
return -1; return -1;
} }
if(d->drive_role != 1)
return 0;
if (d->current_profile == -1 || d->current_is_cd_profile) { if (d->current_profile == -1 || d->current_is_cd_profile) {
d->read_atip(d); d->read_atip(d);
/* >>> some control of success would be nice :) */ /* >>> 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); 0, 0);
return -1; return -1;
} }
*lba = *nwa = 0;
if (d->drive_role != 1)
return 0;
if (o != NULL) if (o != NULL)
d->send_write_parameters(d, o); d->send_write_parameters(d, o);
ret = d->get_nwa(d, trackno, lba, nwa); 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); 0, 0);
return -1; return -1;
} }
*start = 0;
if (d->drive_role != 1)
return 0;
ret = d->read_multi_session_c1(d, &trackno, start); ret = d->read_multi_session_c1(d, &trackno, start);
return ret; return ret;
} }
@ -1483,13 +1541,20 @@ off_t burn_disc_available_space(struct burn_drive *d,
int lba, nwa; int lba, nwa;
if (burn_drive_is_released(d)) if (burn_drive_is_released(d))
goto ex; return 0;
if (d->busy != BURN_DRIVE_IDLE) 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) if (o != NULL)
d->send_write_parameters(d, o); d->send_write_parameters(d, o);
d->get_nwa(d, -1, &lba, &nwa); d->get_nwa(d, -1, &lba, &nwa);
ex:;
if (o != NULL) { if (o != NULL) {
if (o->start_byte > 0) { if (o->start_byte > 0) {
if (o->start_byte > d->media_capacity_remaining) 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 */ /* ts A61226 : free dynamically allocated sub data of struct scsi_mode_data */
int burn_mdata_free_subs(struct scsi_mode_data *m) int burn_mdata_free_subs(struct scsi_mode_data *m)
{ {
if(!m->valid)
return 0;
burn_speed_descriptor_destroy(&(m->speed_descriptors), 1); burn_speed_descriptor_destroy(&(m->speed_descriptors), 1);
return 1; return 1;
} }
@ -1607,6 +1674,8 @@ int burn_drive_get_speedlist(struct burn_drive *d,
struct burn_speed_descriptor *sd, *csd = NULL; struct burn_speed_descriptor *sd, *csd = NULL;
(*speed_list) = NULL; (*speed_list) = NULL;
if(!d->mdata->valid)
return 0;
for (sd = d->mdata->speed_descriptors; sd != NULL; sd = sd->next) { for (sd = d->mdata->speed_descriptors; sd != NULL; sd = sd->next) {
ret = burn_speed_descriptor_new(&csd, NULL, csd, 0); ret = burn_speed_descriptor_new(&csd, NULL, csd, 0);
if (ret <= 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) if (speed_goal < 0)
best_speed = 2000000000; best_speed = 2000000000;
*best_descr = NULL; *best_descr = NULL;
if(!d->mdata->valid)
return 0;
for (sd = d->mdata->speed_descriptors; sd != NULL; sd = sd->next) { for (sd = d->mdata->speed_descriptors; sd != NULL; sd = sd->next) {
if (flag & 1) if (flag & 1)
speed = sd->read_speed; 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->current_is_cd_profile = d->current_is_cd_profile;
o->might_simulate = 0; 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; return 0;
} else if (s == BURN_DISC_APPENDABLE && } else if (s == BURN_DISC_APPENDABLE &&
(wt == BURN_WRITE_SAO || wt == BURN_WRITE_RAW)) { (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); 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;
}

View File

@ -1302,7 +1302,7 @@ struct burn_source *burn_fd_source_new(int datafd, int subfd, off_t size);
/* ts A70328 */ /* ts A70328 */
/** Sets a fixed track size after the data source object has already been /** Sets a fixed track size after the data source object has already been
created. 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 @param size the number of bytes to use as track size
@return <=0 indicates failure , >0 success @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); 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 #ifndef DOXYGEN
BURN_END_DECLS BURN_END_DECLS

View File

@ -377,6 +377,11 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
0x00020143 (SORRY,HIGH) = Read start address not properly aligned 0x00020143 (SORRY,HIGH) = Read start address not properly aligned
0x00020144 (SORRY,HIGH) = SCSI error on read 0x00020144 (SORRY,HIGH) = SCSI error on read
0x00020145 (FATAL,HIGH) = Drive is busy on attempt to read data 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: libdax_audioxtr:

View File

@ -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 burn_write_opts_set_underrun_proof(struct burn_write_opts *opts,
int underrun_proof) int underrun_proof)
{ {
if (!opts->drive->mdata->valid)
return 0;
if (opts->drive->mdata->underrun_proof) { if (opts->drive->mdata->underrun_proof) {
opts->underrun_proof = underrun_proof; opts->underrun_proof = underrun_proof;
return 1; return 1;

View File

@ -12,6 +12,9 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#include <fcntl.h>
#include <errno.h>
#include "sector.h" #include "sector.h"
#include "libburn.h" #include "libburn.h"
#include "drive.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 */ /* ts A70812 : API function */
int burn_read_data(struct burn_drive *d, off_t byte_address, int burn_read_data(struct burn_drive *d, off_t byte_address,
char data[], off_t data_size, off_t *data_count, int flag) char data[], off_t data_size, off_t *data_count, int flag)
{ {
int alignment = 2048, start, upto, chunksize = 1, err, cpy_size, i; 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; char msg[81], *wpt;
struct buffer buf; 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); "Drive is not grabbed on random access write", 0, 0);
return 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) { if ((byte_address % alignment) != 0) {
sprintf(msg, sprintf(msg,
"Read start address not properly aligned (%d bytes)", "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); "Drive is busy on attempt to read data", 0, 0);
return 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->busy = BURN_DRIVE_READING_SYNC;
d->buffer = &buf; 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; cpy_size = data_size - *data_count;
if (flag & 2) if (flag & 2)
d->silent_on_scsi_error = 1; 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) if (flag & 2)
d->silent_on_scsi_error = sose_mem; d->silent_on_scsi_error = sose_mem;
if (err == BE_CANCELLED) { 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++) { for (i = 0; i < chunksize - 1; i++) {
if (flag & 2) if (flag & 2)
d->silent_on_scsi_error = 1; 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) if (flag & 2)
d->silent_on_scsi_error = sose_mem; d->silent_on_scsi_error = sose_mem;
if (err == BE_CANCELLED) if (err == BE_CANCELLED)
@ -359,16 +437,18 @@ int burn_read_data(struct burn_drive *d, off_t byte_address,
wpt += 2048; wpt += 2048;
*data_count += 2048; *data_count += 2048;
} }
d->buffer = NULL; ret = 0; goto ex;
d->busy = BURN_DRIVE_IDLE;
return 0;
} }
memcpy(wpt, d->buffer->data, cpy_size); memcpy(wpt, d->buffer->data, cpy_size);
wpt += cpy_size; wpt += cpy_size;
*data_count += cpy_size; *data_count += cpy_size;
} }
ret = 1;
ex:;
if (fd != -1)
close(fd);
d->buffer = NULL; d->buffer = NULL;
d->busy = BURN_DRIVE_IDLE; d->busy = BURN_DRIVE_IDLE;
return 1; return ret;
} }

View File

@ -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->silent_on_scsi_error = 0;
d->idata = malloc(sizeof(struct burn_scsi_inquiry_data)); d->idata = calloc(1, sizeof(struct burn_scsi_inquiry_data));
d->idata->valid = 0; d->mdata = calloc(1, sizeof(struct scsi_mode_data));
d->mdata = malloc(sizeof(struct scsi_mode_data));
d->mdata->valid = 0;
d->mdata->speed_descriptors = NULL;
/* ts A61007 : obsolete Assert in drive_getcaps() */ /* ts A61007 : obsolete Assert in drive_getcaps() */
if(d->idata == NULL || d->mdata == NULL) { 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); "Could not allocate new drive object", 0, 0);
return -1; return -1;
} }
d->idata->valid = 0;
d->mdata->valid = 0;
d->mdata->speed_descriptors = NULL;
if(!(flag & 1)) { if(!(flag & 1)) {
ret = spc_setup_drive(d); ret = spc_setup_drive(d);
if (ret<=0) if (ret<=0)

View File

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

View File

@ -18,11 +18,15 @@
#define Libburn_sao_can_appenD 1 #define Libburn_sao_can_appenD 1
*/ */
#include <sys/types.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#include <stdlib.h> #include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>
#include "error.h" #include "error.h"
#include "sector.h" #include "sector.h"
#include "libburn.h" #include "libburn.h"
@ -910,6 +914,13 @@ int burn_precheck_write(struct burn_write_opts *o, struct burn_disc *disc,
reason_pt= reasons; reason_pt= reasons;
reasons[0] = 0; 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 */ /* check write mode against write job */
wt = burn_write_opts_auto_write_type(o, disc, reasons, 1); wt = burn_write_opts_auto_write_type(o, disc, reasons, 1);
if (wt == BURN_WRITE_NONE) { 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); reason_pt= reasons + strlen(reasons);
if (d->status == BURN_DISC_UNSUITABLE) if (d->status == BURN_DISC_UNSUITABLE)
goto unsuitable_profile; 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)) if (!burn_disc_write_is_ok(o, disc, (!!silent) << 1))
strcat(reasons, "unsuitable track mode found, "); strcat(reasons, "unsuitable track mode found, ");
if (o->start_byte >= 0) if (o->start_byte >= 0)
strcat(reasons, "write start address not supported, "); 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) { } else if (d->current_profile == 0x13) {
/* DVD-RW Restricted Overwrite */ /* DVD-RW Restricted Overwrite */
if (o->start_byte >= 0 && (o->start_byte % 32768)) 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 */; /* >>> perform OPC if needed */;
/* >>> */;
return 1; 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) void burn_disc_write_sync(struct burn_write_opts *o, struct burn_disc *disc)
{ {
struct cue_sheet *sheet; 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->rlba = -150;
d->toc_temp = 9; 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 */ /* ts A61218 */
if (! d->current_is_cd_profile) { if (! d->current_is_cd_profile) {
ret = burn_dvd_write_sync(o, disc); 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, int burn_random_access_write(struct burn_drive *d, off_t byte_address,
char *data, off_t data_count, int flag) 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; char msg[81], *rpt;
struct buffer buf; 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); "Drive is not grabbed on random access write", 0, 0);
return 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 */ if (d->current_profile == 0x12) /* DVD-RAM */
alignment = 2 * 1024; alignment = 2 * 1024;
if (d->current_profile == 0x13) /* DVD-RW restricted overwrite */ 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); msg, 0, 0);
return 0; return 0;
} }
if (d->busy != BURN_DRIVE_IDLE) { if (d->busy != BURN_DRIVE_IDLE) {
libdax_msgs_submit(libdax_messenger, libdax_msgs_submit(libdax_messenger,
d->global_index, 0x00020140, 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); "Drive is busy on attempt to write random access",0,0);
return 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->busy = BURN_DRIVE_WRITING_SYNC;
d->buffer = &buf; d->buffer = &buf;
@ -2042,15 +2245,26 @@ int burn_random_access_write(struct burn_drive *d, off_t byte_address,
rpt += d->buffer->bytes; rpt += d->buffer->bytes;
d->buffer->sectors = chunksize; d->buffer->sectors = chunksize;
d->nwa = start; 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) { if (err == BE_CANCELLED) {
d->busy = BURN_DRIVE_IDLE; d->busy = BURN_DRIVE_IDLE;
if(fd != -1)
close(fd);
return (-(start * 2048 - byte_address)); return (-(start * 2048 - byte_address));
} }
} }
if (flag & 1) if(d->drive_role == 1 && (flag & 1))
d->sync_cache(d); d->sync_cache(d);
if(fd != -1)
close(fd);
d->buffer = NULL; d->buffer = NULL;
d->busy = BURN_DRIVE_IDLE; d->busy = BURN_DRIVE_IDLE;
return 1; return 1;