Implemented drive role 3, sequential write-only stdio drives (e.g. stdout)
This commit is contained in:
parent
495e668ebc
commit
897ab8fbc6
@ -1 +1 @@
|
||||
#define Cdrskin_timestamP "2007.09.24.062354"
|
||||
#define Cdrskin_timestamP "2007.09.24.135440"
|
||||
|
@ -262,7 +262,7 @@ int burn_drive_grab(struct burn_drive *d, int le)
|
||||
}
|
||||
if(d->drive_role != 1) {
|
||||
d->released = 0;
|
||||
if(d->drive_role == 2) {
|
||||
if(d->drive_role == 2 || d->drive_role == 3) {
|
||||
d->status = BURN_DISC_BLANK;
|
||||
d->current_profile = 0xffff;
|
||||
} else {
|
||||
@ -1118,16 +1118,40 @@ int burn_drive_is_banned(char *device_address)
|
||||
}
|
||||
|
||||
|
||||
/* ts A70903 : will vanish from API */
|
||||
/* ts A70924 */
|
||||
int burn_drive__fd_from_special_adr(char *adr)
|
||||
{
|
||||
int fd = -1, i;
|
||||
|
||||
if (strcmp(adr, "-") == 0)
|
||||
fd = 1;
|
||||
if(strncmp(adr, "/dev/fd/", 8) == 0) {
|
||||
for (i = 8; adr[i]; i++)
|
||||
if (!isdigit(adr[i]))
|
||||
break;
|
||||
if (i> 8 && adr[i] == 0)
|
||||
fd = atoi(adr + 8);
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
/* ts A70903 : Implements adquiration of pseudo drives */
|
||||
int burn_drive_grab_dummy(struct burn_drive_info *drive_infos[], char *fname)
|
||||
{
|
||||
int ret;
|
||||
int ret = -1, fd = -1, role = 0;
|
||||
off_t size = ((off_t) (1024 * 1024 * 1024) * (off_t) 2048);
|
||||
struct burn_drive *d= NULL, *regd_d;
|
||||
struct stat stbuf;
|
||||
|
||||
static int allow_role_3 = 1;
|
||||
|
||||
if (fname[0] != 0) {
|
||||
memset(&stbuf, 0, sizeof(stbuf));
|
||||
fd = burn_drive__fd_from_special_adr(fname);
|
||||
if (fd >= 0)
|
||||
ret = fstat(fd, &stbuf);
|
||||
else
|
||||
ret = stat(fname, &stbuf);
|
||||
if (ret == -1 || S_ISBLK(stbuf.st_mode) ||
|
||||
S_ISREG(stbuf.st_mode)) {
|
||||
@ -1147,13 +1171,20 @@ int burn_drive_grab_dummy(struct burn_drive_info *drive_infos[], char *fname)
|
||||
errno, 0);
|
||||
return 0;
|
||||
}
|
||||
if (fname[0] != 0)
|
||||
role = 2;
|
||||
else
|
||||
role = 0;
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
d= (struct burn_drive *) calloc(1, sizeof(struct burn_drive));
|
||||
if (d == NULL)
|
||||
@ -1161,10 +1192,7 @@ int burn_drive_grab_dummy(struct burn_drive_info *drive_infos[], char *fname)
|
||||
burn_setup_drive(d, fname);
|
||||
d->status = BURN_DISC_EMPTY;
|
||||
|
||||
if (fname[0] != 0)
|
||||
d->drive_role = 2;
|
||||
else
|
||||
d->drive_role = 0;
|
||||
d->drive_role = role;
|
||||
ret = burn_scsi_setup_drive(d, -1, -1, -1, -1, -1, 0);
|
||||
if (ret <= 0)
|
||||
goto ex;
|
||||
@ -1175,7 +1203,7 @@ 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 */
|
||||
d = regd_d;
|
||||
if (d->drive_role == 2) {
|
||||
if (d->drive_role == 2 || d->drive_role == 3) {
|
||||
d->status = BURN_DISC_BLANK;
|
||||
d->current_profile = 0xffff; /* MMC for non-compliant drive */
|
||||
strcpy(d->current_profile_text,"stdio file");
|
||||
@ -1185,7 +1213,7 @@ int burn_drive_grab_dummy(struct burn_drive_info *drive_infos[], char *fname)
|
||||
d->block_types[BURN_WRITE_SAO] = BURN_BLOCK_SAO;
|
||||
d->media_capacity_remaining = size;
|
||||
|
||||
/* >>> ? open file for a test ? */;
|
||||
/* >>> ? open file for a test ? (>>> beware of "-" = stdin) */;
|
||||
|
||||
} else
|
||||
d->current_profile = 0; /* Drives return this if empty */
|
||||
@ -1201,6 +1229,10 @@ int burn_drive_grab_dummy(struct burn_drive_info *drive_infos[], char *fname)
|
||||
strcpy((*drive_infos)[0].vendor,"YOYODYNE");
|
||||
strcpy((*drive_infos)[0].product,"WARP DRIVE");
|
||||
strcpy((*drive_infos)[0].revision,"FX01");
|
||||
} else if (d->drive_role == 3) {
|
||||
strcpy((*drive_infos)[0].vendor,"YOYODYNE");
|
||||
strcpy((*drive_infos)[0].product,"BLACKHOLE");
|
||||
strcpy((*drive_infos)[0].revision,"FX02");
|
||||
} else {
|
||||
strcpy((*drive_infos)[0].vendor,"FERENGI");
|
||||
strcpy((*drive_infos)[0].product,"VAPORWARE");
|
||||
@ -1780,7 +1812,7 @@ off_t burn_disc_available_space(struct burn_drive *d,
|
||||
return 0;
|
||||
if (d->drive_role == 0)
|
||||
return 0;
|
||||
if (d->drive_role == 2) {
|
||||
if (d->drive_role != 1) {
|
||||
if (d->media_capacity_remaining <= 0)
|
||||
d->media_capacity_remaining =
|
||||
((off_t) (1024 * 1024 * 1024) * (off_t) 2048);
|
||||
@ -2011,7 +2043,7 @@ int burn_disc_get_multi_caps(struct burn_drive *d, enum burn_write_types wt,
|
||||
if (d->drive_role == 0)
|
||||
return 0;
|
||||
if (d->drive_role == 2) {
|
||||
/* stdio file dummy drive */
|
||||
/* stdio file drive : random access read-write */
|
||||
o->start_adr = 1;
|
||||
size = d->media_capacity_remaining;
|
||||
burn_os_stdio_capacity(d->devname, &size);
|
||||
@ -2022,6 +2054,12 @@ int burn_disc_get_multi_caps(struct burn_drive *d, enum burn_write_types wt,
|
||||
o->might_do_tao = 2;
|
||||
o->advised_write_mode = BURN_WRITE_TAO;
|
||||
o->might_simulate = 1;
|
||||
} else if (d->drive_role != 1) {
|
||||
/* stdio file drive : sequential access write-only */
|
||||
o->might_do_sao = 4;
|
||||
o->might_do_tao = 2;
|
||||
o->advised_write_mode = BURN_WRITE_TAO;
|
||||
o->might_simulate = 1;
|
||||
} else if (s != BURN_DISC_BLANK && s != BURN_DISC_APPENDABLE) {
|
||||
return 0;
|
||||
} else if (s == BURN_DISC_APPENDABLE &&
|
||||
@ -2251,6 +2289,12 @@ int burn_drive_equals_adr(struct burn_drive *d1, char *adr2_in, int role2)
|
||||
stat_ret2 = stat(adr2, &stbuf2);
|
||||
conv_ret2 = burn_drive_convert_fs_adr(adr2, conv_adr2);
|
||||
|
||||
/* roles 2 and 3 have the same name space and object interpretation */
|
||||
if (role1 == 3)
|
||||
role1 = 2;
|
||||
if (role2 == 3)
|
||||
role2 = 2;
|
||||
|
||||
if (strcmp(adr1, adr2) == 0 && role1 == role2)
|
||||
return(1); /* equal role and address */
|
||||
if (role1 == 1 && role2 == 1) {
|
||||
|
@ -114,4 +114,11 @@ int burn_disc_get_write_mode_demands(struct burn_disc *disc,
|
||||
struct burn_write_opts *opts,
|
||||
struct burn_disc_mode_demands *result, int flag);
|
||||
|
||||
|
||||
/* ts A70924 : convert a special stdio address into fd number.
|
||||
@return >0 is a valid fd , -1 indicates unsuitable address string.
|
||||
*/
|
||||
int burn_drive__fd_from_special_adr(char *adr);
|
||||
|
||||
|
||||
#endif /* __DRIVE */
|
||||
|
@ -622,9 +622,11 @@ void burn_allow_untested_profiles(int yes);
|
||||
|
||||
|
||||
/* ts A60823 */
|
||||
/** Aquire a drive with known persistent address. This is the sysadmin friendly
|
||||
way to open one drive and to leave all others untouched. It bundles
|
||||
the following API calls to form a non-obtrusive way to use libburn:
|
||||
/** Aquire a drive with known persistent address.
|
||||
|
||||
This is the sysadmin friendly way to open one drive and to leave all
|
||||
others untouched. It bundles the following API calls to form a
|
||||
non-obtrusive way to use libburn:
|
||||
burn_drive_add_whitelist() , burn_drive_scan() , burn_drive_grab()
|
||||
You are *strongly urged* to use this call whenever you know the drive
|
||||
address in advance.
|
||||
@ -639,28 +641,48 @@ void burn_allow_untested_profiles(int yes);
|
||||
Another way is to drop the unwanted drives by burn_drive_info_forget().
|
||||
|
||||
Operating on multiple drives:
|
||||
|
||||
Different than with burn_drive_scan() it is allowed to call
|
||||
burn_drive_scan_and_grab() without giving up any other scanned drives. So
|
||||
this call can be used to get a collection of more than one aquired drives.
|
||||
The attempt to aquire the same drive twice will fail, though.
|
||||
|
||||
Pseudo-drives:
|
||||
|
||||
burn_drive_scan_and_grab() is able to aquire virtual drives which will
|
||||
accept options much like a MMC burner drive. Many of those options will not
|
||||
cause any effect, though. The address of a pseudo-drive begins with
|
||||
prefix "stdio:" optionally followed by the path to an existing regular
|
||||
file, or to a not yet existing file, or to an existing block device.
|
||||
Example: "stdio:/tmp/pseudo_drive"
|
||||
If the path is empty then the resulting pseudo-drive is a null-drive.
|
||||
A null-drive will pretend to have loaded no media and support no writing.
|
||||
A pseudo-drive with a non-empty path is called a stdio-drive.
|
||||
It will perform all its eventual data transfer activities on a file
|
||||
prefix "stdio:" followed by a path.
|
||||
Examples: "stdio:/tmp/pseudo_drive" , "stdio:/dev/null" , "stdio:-"
|
||||
|
||||
If the path is empty, the result is a null-drive = drive role 0.
|
||||
It pretends to have loaded no media and supports no reading or writing.
|
||||
|
||||
If the path leads to an existing regular file, or to a not yet existing
|
||||
file, or to an existing block device, then the result is a random access
|
||||
stdio-drive capable of reading and writing = drive role 2.
|
||||
|
||||
If the path leads to an existing file of any type other than directory,
|
||||
then the result is a sequential write-only stdio-drive = drive role 3.
|
||||
|
||||
The special address form "stdio:/dev/fd/<number>" is interpreted literally
|
||||
as reference to open file descriptor <number>. This address form coincides
|
||||
with real files on some systems, but it is in fact hardcoded in libburn.
|
||||
Special address "stdio:-" means stdout = "stdio:/dev/fd/1".
|
||||
The role of such a drive is determined by the file type obtained via
|
||||
fstat(<number>).
|
||||
|
||||
Roles 2 and 3 perform all their 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 0xffff,
|
||||
it can simulate writing and it issues no realistic write space information.
|
||||
The media profile is reported as 0xffff. Write space information from those
|
||||
media is not necessarily realistic.
|
||||
|
||||
The capabilities of role 2 resemble DVD-RAM but it can simulate writing.
|
||||
If the path does not exist in the filesystem yet, it is attempted to create
|
||||
it as a regular file as soon as write operations are started.
|
||||
|
||||
The capabilities of role 3 resemble a blank DVD-R.
|
||||
|
||||
One may distinguish pseudo-drives from MMC drives by call
|
||||
burn_drive_get_drive_role().
|
||||
|
||||
@ -2004,7 +2026,8 @@ int burn_read_data(struct burn_drive *d, off_t byte_address,
|
||||
@param d The drive to inquire
|
||||
@return 0= null-drive
|
||||
1= real MMC drive
|
||||
2= stdio-drive
|
||||
2= stdio-drive, random access, read-write
|
||||
3= stdio-drive, sequential, write-only
|
||||
*/
|
||||
int burn_drive_get_drive_role(struct burn_drive *d);
|
||||
|
||||
|
@ -332,7 +332,7 @@ int burn_read_data(struct burn_drive *d, off_t byte_address,
|
||||
libdax_msgs_submit(libdax_messenger,
|
||||
d->global_index, 0x00020142,
|
||||
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
|
||||
"Drive is not grabbed on random access write", 0, 0);
|
||||
"Drive is not grabbed on random access read", 0, 0);
|
||||
return 0;
|
||||
}
|
||||
if (d->drive_role == 0) {
|
||||
@ -341,6 +341,12 @@ int burn_read_data(struct burn_drive *d, off_t byte_address,
|
||||
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
|
||||
"Drive is a virtual placeholder (null-drive)", 0, 0);
|
||||
return 0;
|
||||
} else if (d->drive_role == 3) {
|
||||
libdax_msgs_submit(libdax_messenger, d->global_index,
|
||||
0x00020151,
|
||||
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
|
||||
"Read attempt on write-only drive", 0, 0);
|
||||
return 0;
|
||||
}
|
||||
if ((byte_address % alignment) != 0) {
|
||||
sprintf(msg,
|
||||
|
@ -121,7 +121,12 @@ 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 */
|
||||
/* ts A70902:
|
||||
0=null-emulation
|
||||
1=MMC drive ,
|
||||
2=stdio random read-write
|
||||
3=stdio sequential write-only
|
||||
*/
|
||||
int drive_role;
|
||||
|
||||
int bus_no;
|
||||
|
@ -951,10 +951,11 @@ int burn_precheck_write(struct burn_write_opts *o, struct burn_disc *disc,
|
||||
if (o->start_byte >= 0 && (o->start_byte % 32768))
|
||||
strcat(reasons,
|
||||
"write start address not properly aligned to 32k, ");
|
||||
} else if (d->current_profile == 0x11 || d->current_profile == 0x14 ||
|
||||
} else if (d->drive_role == 3 ||
|
||||
d->current_profile == 0x11 || d->current_profile == 0x14 ||
|
||||
d->current_profile == 0x15 ||
|
||||
d->current_profile == 0x1b || d->current_profile == 0x2b ) {
|
||||
/* DVD-R* Sequential , DVD+R[/DL] */
|
||||
/* DVD-R* Sequential , DVD+R[/DL] , sequential stdio "drive" */
|
||||
if (o->start_byte >= 0)
|
||||
strcat(reasons, "write start address not supported, ");
|
||||
} else {
|
||||
@ -1624,16 +1625,22 @@ int burn_stdio_open_write(struct burn_drive *d, off_t start_byte,
|
||||
|
||||
if (d->devname[0] == 0) /* null drives should not come here */
|
||||
return -1;
|
||||
fd = burn_drive__fd_from_special_adr(d->devname);
|
||||
if (fd >= 0)
|
||||
fd = dup(fd); /* check validity and make closeable */
|
||||
else
|
||||
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);
|
||||
d->cancel = 1;
|
||||
return -1;
|
||||
}
|
||||
if (start_byte < 0)
|
||||
start_byte = 0;
|
||||
if (d->drive_role == 2)
|
||||
if (lseek(fd, start_byte, SEEK_SET)==-1) {
|
||||
sprintf(msg, "Cannot address start byte %.f",
|
||||
(double) start_byte);
|
||||
@ -1642,6 +1649,7 @@ int burn_stdio_open_write(struct burn_drive *d, off_t start_byte,
|
||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
||||
msg, errno, 0);
|
||||
close(fd);
|
||||
d->cancel = 1;
|
||||
fd = -1;
|
||||
}
|
||||
d->nwa = start_byte / sector_size;
|
||||
@ -1761,6 +1769,8 @@ int burn_stdio_sync_cache(int fd, struct burn_drive *d, int flag)
|
||||
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
|
||||
"syncing cache (stdio fsync)", 0, 0);
|
||||
if (fsync(fd) != 0) {
|
||||
if (errno == EINVAL) /* E.g. /dev/null cannot fsync */
|
||||
return 1;
|
||||
libdax_msgs_submit(libdax_messenger, d->global_index,
|
||||
0x00020148,
|
||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
||||
@ -1967,10 +1977,10 @@ int burn_stdio_write_sync(struct burn_write_opts *o,
|
||||
d->progress.sectors = 0;
|
||||
ret = 1;
|
||||
ex:;
|
||||
if (d->stdio_fd != -1) {
|
||||
if (d->stdio_fd >= 0)
|
||||
close(d->stdio_fd);
|
||||
d->stdio_fd = -1;
|
||||
}
|
||||
|
||||
/* update media state records */
|
||||
burn_drive_mark_unready(d);
|
||||
|
||||
@ -2203,7 +2213,7 @@ int burn_random_access_write(struct burn_drive *d, off_t byte_address,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(d->drive_role != 1)
|
||||
if(d->drive_role == 2)
|
||||
alignment = 2 * 1024;
|
||||
if (d->current_profile == 0x12) /* DVD-RAM */
|
||||
alignment = 2 * 1024;
|
||||
@ -2277,7 +2287,7 @@ int burn_random_access_write(struct burn_drive *d, off_t byte_address,
|
||||
}
|
||||
if (err == BE_CANCELLED) {
|
||||
d->busy = BURN_DRIVE_IDLE;
|
||||
if(fd != -1)
|
||||
if(fd >= 0)
|
||||
close(fd);
|
||||
return (-(start * 2048 - byte_address));
|
||||
}
|
||||
@ -2290,7 +2300,7 @@ int burn_random_access_write(struct burn_drive *d, off_t byte_address,
|
||||
burn_stdio_sync_cache(fd, d, 0);
|
||||
}
|
||||
|
||||
if(fd != -1)
|
||||
if(fd >= 0)
|
||||
close(fd);
|
||||
d->buffer = NULL;
|
||||
d->busy = BURN_DRIVE_IDLE;
|
||||
|
Loading…
Reference in New Issue
Block a user