New API calls burn_drive_grab_dummy(), burn_drive_get_drive_role()
This commit is contained in:
parent
d4eed9925d
commit
1c3a79629c
@ -1 +1 @@
|
||||
#define Cdrskin_timestamP "2007.09.01.182319"
|
||||
#define Cdrskin_timestamP "2007.09.04.224905"
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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…
Reference in New Issue
Block a user