New API call burn_allow_drive_role_4()

This commit is contained in:
Thomas Schmitt 2011-03-13 13:07:46 +00:00
parent 1b166f484d
commit 402f4c0b04
8 changed files with 154 additions and 35 deletions

View File

@ -1 +1 @@
#define Cdrskin_timestamP "2011.03.12.093520" #define Cdrskin_timestamP "2011.03.13.130746"

View File

@ -659,6 +659,14 @@ void burn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc)
"Drive is a virtual placeholder (null-drive)", 0, 0); "Drive is a virtual placeholder (null-drive)", 0, 0);
return; return;
} }
if (d->drive_role == 4) {
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020181,
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
"Pseudo-drive is a read-only file. Cannot write.",
0, 0);
return;
}
/* ts A61007 : obsolete Assert in spc_select_write_params() */ /* ts A61007 : obsolete Assert in spc_select_write_params() */
if (d->drive_role == 1 && d->mdata->valid <= 0) { if (d->drive_role == 1 && d->mdata->valid <= 0) {

View File

@ -60,6 +60,10 @@ static int drivetop = -1;
/* ts A80410 : in init.c */ /* ts A80410 : in init.c */
extern int burn_support_untested_profiles; extern int burn_support_untested_profiles;
/* ts B10312 : in init.c */
extern int burn_drive_role_4_allowed;
/* ts A61021 : the unspecific part of sg.c:enumerate_common() /* ts A61021 : the unspecific part of sg.c:enumerate_common()
*/ */
int burn_setup_drive(struct burn_drive *d, char *fname) int burn_setup_drive(struct burn_drive *d, char *fname)
@ -1386,6 +1390,7 @@ static int burn_drive__is_rdwr(char *fname, int *stat_ret,
read_size = (off_t) 0x7ffffff0 * (off_t) 2048; read_size = (off_t) 0x7ffffff0 * (off_t) 2048;
} }
} }
if (is_rdwr && fd >= 0) { if (is_rdwr && fd >= 0) {
getfl_ret = fcntl(fd, F_GETFL); getfl_ret = fcntl(fd, F_GETFL);
@ -1411,6 +1416,37 @@ fprintf(stderr, "LIBBURN_DEBUG: burn_drive__is_rdwr: getfl_ret = %lX , O_RDWR =
} }
static int burn_role_by_access(char *fname, int flag)
{
/* We normally need _LARGEFILE64_SOURCE defined by the build system.
Nevertheless the system might use large address integers by default.
*/
#ifndef O_LARGEFILE
#define O_LARGEFILE 0
#endif
int fd;
fd = open(fname, O_RDWR | O_LARGEFILE);
if (fd != -1) {
close(fd);
return 2;
}
fd = open(fname, O_RDONLY | O_LARGEFILE);
if (fd != -1) {
close(fd);
return 4;
}
fd = open(fname, O_WRONLY | O_LARGEFILE);
if (fd != -1) {
close(fd);
return 3;
}
if (flag & 1)
return 0;
return 2;
}
/* ts A70903 : Implements adquiration of pseudo drives */ /* ts A70903 : Implements adquiration of pseudo drives */
int burn_drive_grab_dummy(struct burn_drive_info *drive_infos[], char *fname) int burn_drive_grab_dummy(struct burn_drive_info *drive_infos[], char *fname)
{ {
@ -1422,8 +1458,6 @@ int burn_drive_grab_dummy(struct burn_drive_info *drive_infos[], char *fname)
struct burn_drive *d= NULL, *regd_d; struct burn_drive *d= NULL, *regd_d;
struct stat stbuf; struct stat stbuf;
static int allow_role_3 = 1;
if (fname[0] != 0) { if (fname[0] != 0) {
is_rdwr = burn_drive__is_rdwr(fname, &stat_ret, &stbuf, is_rdwr = burn_drive__is_rdwr(fname, &stat_ret, &stbuf,
&read_size, 1); &read_size, 1);
@ -1445,22 +1479,18 @@ int burn_drive_grab_dummy(struct burn_drive_info *drive_infos[], char *fname)
return 0; return 0;
} }
if (fname[0] != 0) { if (fname[0] != 0) {
if (is_rdwr == 2 &&
/* >>> as soon as new role 4 is introduced: (burn_drive_role_4_allowed & 1))
if (is_rdwr == 2) role = 4; else role = 4;
*/ else
role = 2;
role = 2; if (stat_ret != -1 && is_rdwr == 1 &&
(burn_drive_role_4_allowed & 3) == 3)
role = burn_role_by_access(fname,
!!(burn_drive_role_4_allowed & 4));
} else } else
role = 0; role = 0;
} else { } else {
if(S_ISDIR(stbuf.st_mode) || !allow_role_3) {
libdax_msgs_submit(libdax_messenger, -1,
0x00020149,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Unsuitable filetype for pseudo-drive", 0, 0);
return 0;
}
role = 3; role = 3;
} }
} }
@ -1481,22 +1511,28 @@ int burn_drive_grab_dummy(struct burn_drive_info *drive_infos[], char *fname)
} }
free((char *) d); /* all sub pointers have been copied to *regd_d */ free((char *) d); /* all sub pointers have been copied to *regd_d */
d = regd_d; d = regd_d;
if (d->drive_role == 2 || d->drive_role == 3) { if (d->drive_role == 2 || d->drive_role == 3 || d->drive_role == 4) {
d->status = BURN_DISC_BLANK; if (d->drive_role == 4) {
d->current_profile = 0xffff; /* MMC for non-compliant drive */ d->status = BURN_DISC_FULL;
/* MMC for non-compliant drive */
d->current_profile = 0xffff;
d->block_types[BURN_WRITE_TAO] = 0;
d->block_types[BURN_WRITE_SAO] = 0;
} else {
d->status = BURN_DISC_BLANK;
/* MMC for non-compliant drive */
d->current_profile = 0xffff;
d->block_types[BURN_WRITE_TAO] = BURN_BLOCK_MODE1;
d->block_types[BURN_WRITE_SAO] = BURN_BLOCK_SAO;
}
strcpy(d->current_profile_text,"stdio file"); strcpy(d->current_profile_text,"stdio file");
d->current_is_cd_profile = 0; d->current_is_cd_profile = 0;
d->current_is_supported_profile = 1; d->current_is_supported_profile = 1;
d->block_types[BURN_WRITE_TAO] = BURN_BLOCK_MODE1;
d->block_types[BURN_WRITE_SAO] = BURN_BLOCK_SAO;
if (read_size >= 0) if (read_size >= 0)
/* despite its name : last valid address, not size */ /* despite its name : last valid address, not size */
d->media_read_capacity = d->media_read_capacity =
read_size / 2048 - !(read_size % 2048); read_size / 2048 - !(read_size % 2048);
burn_drive_set_media_capacity_remaining(d, size); burn_drive_set_media_capacity_remaining(d, size);
/* >>> ? open file for a test ? (>>> beware of "-" = stdin) */;
} else } else
d->current_profile = 0; /* Drives return this if empty */ d->current_profile = 0; /* Drives return this if empty */
@ -1515,6 +1551,10 @@ int burn_drive_grab_dummy(struct burn_drive_info *drive_infos[], char *fname)
strcpy((*drive_infos)[0].vendor,"YOYODYNE"); strcpy((*drive_infos)[0].vendor,"YOYODYNE");
strcpy((*drive_infos)[0].product,"BLACKHOLE"); strcpy((*drive_infos)[0].product,"BLACKHOLE");
strcpy((*drive_infos)[0].revision,"FX02"); strcpy((*drive_infos)[0].revision,"FX02");
} else if (d->drive_role == 4) {
strcpy((*drive_infos)[0].vendor,"YOYODYNE");
strcpy((*drive_infos)[0].product,"WARP DRIVE");
strcpy((*drive_infos)[0].revision,"FX03");
} else { } else {
strcpy((*drive_infos)[0].vendor,"FERENGI"); strcpy((*drive_infos)[0].vendor,"FERENGI");
strcpy((*drive_infos)[0].product,"VAPORWARE"); strcpy((*drive_infos)[0].product,"VAPORWARE");
@ -2448,7 +2488,7 @@ 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 (d->drive_role == 0) if (d->drive_role == 0 || d->drive_role == 4)
return 0; return 0;
if (d->drive_role == 2) { if (d->drive_role == 2) {
/* stdio file drive : random access read-write */ /* stdio file drive : random access read-write */
@ -2711,12 +2751,9 @@ int burn_drive_equals_adr(struct burn_drive *d1, char *adr2_in, int role2)
if (fd != -1) if (fd != -1)
exact_role_matters = 1; exact_role_matters = 1;
ret = burn_drive__is_rdwr(adr2, NULL, NULL, NULL, 1); ret = burn_drive__is_rdwr(adr2, NULL, NULL, NULL, 1);
if (ret == 2 && burn_drive_role_4_allowed)
/* >>> as soon as new role 4 is introduced: role2 = 4;
if (ret == 2) role2 = 4; else else if (ret > 0)
*/
if (ret == 1)
role2 = 2; role2 = 2;
else else
role2 = 3; role2 = 3;

View File

@ -105,6 +105,14 @@ int burn_support_untested_profiles = 0;
*/ */
int burn_sg_log_scsi = 0; int burn_sg_log_scsi = 0;
/* ts B10312 :
Whether to map random-access readonly files to drive role 4.
Else it is role 2 overwriteable drive
*/
int burn_drive_role_4_allowed = 0;
/* ts A60925 : ticket 74 */ /* ts A60925 : ticket 74 */
/** Create the messenger object for libburn. */ /** Create the messenger object for libburn. */
int burn_msgs_initialize(void) int burn_msgs_initialize(void)
@ -565,3 +573,10 @@ void burn_set_scsi_logging(int flag)
{ {
burn_sg_log_scsi = flag & 7; burn_sg_log_scsi = flag & 7;
} }
/* ts B10312 API */
void burn_allow_drive_role_4(int allowed)
{
burn_drive_role_4_allowed = (allowed & 7);
}

View File

@ -3004,7 +3004,7 @@ 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);
/* A70904 */ /* ts A70904 */
/** Inquire whether the drive object is a real MMC drive or a pseudo-drive /** Inquire whether the drive object is a real MMC drive or a pseudo-drive
created by a stdio: address. created by a stdio: address.
@param d The drive to inquire @param d The drive to inquire
@ -3012,11 +3012,41 @@ int burn_read_data(struct burn_drive *d, off_t byte_address,
1= real MMC drive 1= real MMC drive
2= stdio-drive, random access, read-write 2= stdio-drive, random access, read-write
3= stdio-drive, sequential, write-only 3= stdio-drive, sequential, write-only
4= stdio-drive, random access, read-only
(only if enabled by burn_allow_drive_role_4())
@since 0.4.0 @since 0.4.0
*/ */
int burn_drive_get_drive_role(struct burn_drive *d); int burn_drive_get_drive_role(struct burn_drive *d);
/* ts B10312 */
/** Allow drive role 4 "random access read-only" drive.
By default a random access file assumes drive role 2 "read-write"
regardless whether it is actually readable or writeable.
If enabled, random-access file objects which recognizably allow no
writing will be classified as role 4.
Candidates are drive addresses of the form stdio:/dev/fd/# , where # is
the integer number of an open file descriptor. If this descriptor was
opened read-only, then it gets role 4.
Other paths may get tested by an attempt to open them for read-write
(role 2) resp. read-only (role 4) resp. write-only (role 3). See bit1.
read-only
@param allowed Bitfield for control purposes:
bit0= Enable role 4 for drives which get aquired
after this call
bit1= with bit0:
Test whether the file can be opened for
read-write resp. read-only resp. write-only.
Classify as roles 2 resp. 4 resp. 3.
bit2= with bit0 and bit1:
Classify files which cannot be opened at all
as role 0 : useless dummy.
Else classify as role 2.
@since 1.0.6
*/
void burn_allow_drive_role_4(int allowed);
/* ts A70923 */ /* ts A70923 */
/** Find out whether a given address string would lead to the given drive /** Find out whether a given address string would lead to the given drive
object. This should be done in advance for track source addresses object. This should be done in advance for track source addresses

View File

@ -2,6 +2,7 @@ LIBBURN4 {
global: global:
burn_abort; burn_abort;
burn_abort_pacifier; burn_abort_pacifier;
burn_allow_drive_role_4;
burn_allow_untested_profiles; burn_allow_untested_profiles;
burn_disc_add_session; burn_disc_add_session;
burn_disc_available_space; burn_disc_available_space;

View File

@ -566,6 +566,7 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
0x0002017e (FAILURE,HIGH) = Failed to close track, session, or disc 0x0002017e (FAILURE,HIGH) = Failed to close track, session, or disc
0x0002017f (FAILURE,HIGH) = Failed to synchronize drive cache 0x0002017f (FAILURE,HIGH) = Failed to synchronize drive cache
0x00020180 (FAILURE,HIGH) = Premature end of input encountered 0x00020180 (FAILURE,HIGH) = Premature end of input encountered
0x00020181 (FAILURE,HIGH) = Pseudo-drive is a read-only file. Cannot write.
libdax_audioxtr: libdax_audioxtr:
0x00020200 (SORRY,HIGH) = Cannot open audio source file 0x00020200 (SORRY,HIGH) = Cannot open audio source file

View File

@ -1005,9 +1005,12 @@ 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) { if (d->drive_role == 0 || d->drive_role == 4) {
sprintf(reasons, if (d->drive_role == 0)
"DRIVE: is a virtual placeholder (null-drive)"); sprintf(reasons,
"DRIVE: is a virtual placeholder (null-drive)");
else
sprintf(reasons, "DRIVE: read-only pseudo drive");
no_media = 1; no_media = 1;
goto ex; goto ex;
} }
@ -2042,6 +2045,14 @@ int burn_stdio_open_write(struct burn_drive *d, off_t start_byte,
char msg[160]; char msg[160];
off_t lseek_res; off_t lseek_res;
if(d->drive_role == 4) {
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020181,
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
"Pseudo-drive is a read-only file. Cannot write.",
0, 0);
return 0;
}
if (d->devname[0] == 0) /* null drives should not come here */ if (d->devname[0] == 0) /* null drives should not come here */
return -1; return -1;
fd = burn_drive__fd_from_special_adr(d->devname); fd = burn_drive__fd_from_special_adr(d->devname);
@ -2421,6 +2432,14 @@ calloc() seems not to have the desired effect. valgrind warns:
d->rlba = -150; d->rlba = -150;
d->toc_temp = 9; d->toc_temp = 9;
if(d->drive_role == 4) {
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020181,
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
"Pseudo-drive is a read-only file. Cannot write.",
0, 0);
goto fail_wo_sync;
}
/* ts A70904 */ /* ts A70904 */
if (d->drive_role != 1) { if (d->drive_role != 1) {
ret = burn_stdio_write_sync(o, disc); ret = burn_stdio_write_sync(o, disc);
@ -2644,6 +2663,14 @@ int burn_random_access_write(struct burn_drive *d, off_t byte_address,
"Drive is a virtual placeholder (null-drive)", 0, 0); "Drive is a virtual placeholder (null-drive)", 0, 0);
return 0; return 0;
} }
if(d->drive_role == 4) {
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020181,
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
"Pseudo-drive is a read-only file. Cannot write.",
0, 0);
return 0;
}
if(d->drive_role == 2) if(d->drive_role == 2)
alignment = 2 * 1024; alignment = 2 * 1024;