Integrated elmom patch proposal #3 from ticket #62

This commit is contained in:
Thomas Schmitt 2006-09-04 19:11:04 +00:00
parent da15bba025
commit bbdb40ff0f
5 changed files with 139 additions and 43 deletions

View File

@ -25,20 +25,28 @@ static int drivetop = -1;
int burn_drive_is_open(struct burn_drive *d);
void burn_drive_free(void)
/* 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)
{
int i;
struct burn_drive *d;
for (i = 0; i < drivetop + 1; i++) {
d = &drive_array[i];
if (d->global_index == -1)
return;
/* ts A60822 : close open fds before forgetting them */
if (burn_drive_is_open(d))
close(d->fd);
free((void *) d->idata);
free((void *) d->mdata);
free((void *) d->toc_entry);
free(d->devname);
d->global_index = -1;
}
void burn_drive_free_all(void)
{
int i;
for (i = 0; i < drivetop + 1; i++)
burn_drive_free(&(drive_array[i]));
drivetop = -1;
memset(drive_array, 0, sizeof(drive_array));
}
@ -86,6 +94,10 @@ int burn_drive_grab(struct burn_drive *d, int le)
struct burn_drive *burn_drive_register(struct burn_drive *d)
{
#ifdef Libburn_ticket_62_re_register_is_possiblE
int i;
#endif
d->block_types[0] = 0;
d->block_types[1] = 0;
d->block_types[2] = 0;
@ -100,9 +112,33 @@ struct burn_drive *burn_drive_register(struct burn_drive *d)
d->toc_entry = NULL;
d->disc = NULL;
d->erasable = 0;
#ifdef Libburn_ticket_62_re_register_is_possiblE
/* ts A60904 : ticket 62, contribution by elmom */
/* Not yet accepted because no use case seen yet */
/* This is supposed to find an already freed drive struct among
all the the ones that have been used before */
for (i = 0; i < drivetop + 1; i++)
if (drive_array[i].global_index == -1)
break;
d->global_index = i;
memcpy(&drive_array[i], d, sizeof(struct burn_drive));
pthread_mutex_init(&drive_array[i].access_lock, NULL);
if (drivetop < i)
drivetop = i;
return &(drive_array[i]);
#else /* Libburn_ticket_62_re_register_is_possiblE */
/* old A60904 : */
/* Still active by default */
memcpy(&drive_array[drivetop + 1], d, sizeof(struct burn_drive));
pthread_mutex_init(&drive_array[drivetop + 1].access_lock, NULL);
return &drive_array[++drivetop];
#endif /* ! Libburn_ticket_62_re_register_is_possiblE */
}
void burn_drive_release(struct burn_drive *d, int le)
@ -138,6 +174,11 @@ void burn_wait_all(void)
finished = 1;
d = drive_array;
for (i = burn_drive_count(); i > 0; --i, ++d) {
/* ts A60904 : ticket 62, contribution by elmom */
if (d->global_index==-1)
continue;
assert(d->released);
}
if (!finished)
@ -284,10 +325,13 @@ int burn_drive_scan_sync(struct burn_drive_info *drives[],
unsigned int *n_drives)
{
/* state vars for the scan process */
static int scanning = 0, scanned, found;
static unsigned num_scanned, count;
/* ts A60904 : did set some default values to feel comfortable */
static int scanning = 0, scanned = 0, found = 0;
static unsigned num_scanned = 0, count = 0;
unsigned int i;
#ifdef Libburn_ticket_62_enable_redundant_asserT
struct burn_drive *d;
#endif
assert(burn_running);
@ -298,10 +342,14 @@ int burn_drive_scan_sync(struct burn_drive_info *drives[],
before checking for the released
state */
/* ts A60904 : ticket 62, contribution by elmom */
/* this is redundant with what is done in burn_wait_all() */
#ifdef Libburn_ticket_62_enable_redundant_asserT
d = drive_array;
count = burn_drive_count();
for (i = 0; i < count; ++i, ++d)
assert(d->released == 1);
#endif /* Libburn_ticket_62_enable_redundant_asserT */
/* refresh the lib's drives */
sg_enumerate();
@ -337,10 +385,27 @@ int burn_drive_scan_sync(struct burn_drive_info *drives[],
return 0;
}
void burn_drive_info_free(struct burn_drive_info *info)
void burn_drive_info_free(struct burn_drive_info drive_infos[])
{
free(info);
burn_drive_free();
/* 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) /* and this NULL test is deadly necessary */
free((void *) drive_infos);
burn_drive_free_all();
}
/* Experimental API call */
int burn_drive_info_forget(struct burn_drive_info *info)
{
burn_drive_free(info->drive);
return 1;
}
struct burn_disc *burn_drive_get_disc(struct burn_drive *d)
@ -433,7 +498,7 @@ int burn_drive_is_open(struct burn_drive *d)
/* ts A60823 */
/** Aquire a drive with known persistent address.
*/
int burn_drive_scan_and_grab(struct burn_drive_info *drives[], char* adr,
int burn_drive_scan_and_grab(struct burn_drive_info *drive_infos[], char* adr,
int load)
{
unsigned int n_drives;
@ -441,19 +506,19 @@ int burn_drive_scan_and_grab(struct burn_drive_info *drives[], char* adr,
burn_drive_clear_whitelist();
burn_drive_add_whitelist(adr);
while (!burn_drive_scan(drives, &n_drives));
while (!burn_drive_scan(drive_infos, &n_drives));
if (n_drives <= 0)
return 0;
if (load) {
/* RIP-14.5 + LITE-ON 48125S produce a false status
if tray was unloaded */
/* Therefore the first grab is just for loading */
ret= burn_drive_grab(drives[0]->drive, 1);
ret= burn_drive_grab(drive_infos[0]->drive, 1);
if (ret != 1)
return -1;
burn_drive_release(drives[0]->drive,0);
burn_drive_release(drive_infos[0]->drive,0);
}
ret = burn_drive_grab(drives[0]->drive, load);
ret = burn_drive_grab(drive_infos[0]->drive, load);
if (ret != 1)
return -1;
return 1;

View File

@ -42,7 +42,8 @@ int burn_sector_length_write(struct burn_drive *d);
int burn_track_control(struct burn_drive *d, int);
void burn_write_empty_sector(int fd);
void burn_write_empty_subcode(int fd);
void burn_drive_free(void);
void burn_drive_free(struct burn_drive *d);
void burn_drive_free_all(void);
int burn_drive_scan_sync(struct burn_drive_info *drives[],
unsigned int *n_drives);

View File

@ -46,7 +46,8 @@ void burn_finish(void)
burn_wait_all();
burn_drive_free();
/* ts A60904 : ticket 62, contribution by elmom : name addon "_all" */
burn_drive_free_all();
burn_running = 0;
}

View File

@ -479,6 +479,7 @@ struct burn_message* burn_get_message(void);
/** Frees a burn_message structure */
void burn_message_free(struct burn_message *msg);
/* 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
@ -493,8 +494,8 @@ void burn_message_free(struct burn_message *msg);
burn_drive_scan().
You may start a new libburn session and should then use the function
described here with an address obtained after burn_drive_scan() via
a call of burn_drive_get_adr(&(drives[driveno]), adr) .
@param drives On success returns a one element array with the drive
a call of burn_drive_get_adr(&(drive_infos[driveno]), adr) .
@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()
@ -509,46 +510,63 @@ void burn_message_free(struct burn_message *msg);
tray door, etc).
@return 1 = success , 0 = drive not found , -1 = other error
*/
int burn_drive_scan_and_grab(struct burn_drive_info *drives[], char* adr,
int load);
int burn_drive_scan_and_grab(struct burn_drive_info *drive_infos[],
char* adr, int load);
/* ts A51221 */
/** Maximum number of particularly permissible drive addresses */
#define BURN_DRIVE_WHITELIST_LEN 255
/** Add a device to the list of permissible drives. As soon as some entry is in
the whitelist all non-listed drives are banned from enumeration.
the whitelist all non-listed drives are banned from scanning.
@return 1 success, <=0 failure
*/
int burn_drive_add_whitelist(char *device_address);
/** Remove all drives from whitelist. This enables all possible drives. */
void burn_drive_clear_whitelist(void);
/** Scans for drives. This function MUST be called until it returns nonzero.
No drives can be in use when this is called or it will assert.
All drive pointers are invalidated by using this function. Do NOT store
drive pointers across calls to this function or death AND pain will ensue.
When the app is done with the burn_drive_info array, it must be freed with
burn_drive_info_free()
@param drives Returns an array of drives (cdroms/burners). The returned
array should be freed when it is no longer needed, and
before calling this function again to rescan.
@param n_drives Returns the number of hardware drives in @c drives.
After this call all drives depicted by the returned array are subject
to eventual (O_EXCL) locking. See burn_preset_device_open(). This state
ends either with burn_drive_info_forget() or with burn_drive_release().
It is unfriendly to other processes on the system to hold drives locked
which one does not definitely plan to use soon.
@param drive_infos Returns an array of drive info items (cdroms/burners).
The returned array must be freed by burn_drive_info_free()
before burn_finish(), and also before calling this function
burn_drive_scan() again.
@param n_drives Returns the number of drive items in drive_infos.
@return Zero while scanning is not complete; non-zero when it is finished.
*/
int burn_drive_scan(struct burn_drive_info *drives[],
int burn_drive_scan(struct burn_drive_info *drive_infos[],
unsigned int *n_drives);
/** Frees a burn_drive_info array returned by burn_drive_scan
@param info The array to free
/* ts A60904 : ticket 62, contribution by elmom */
/** EXPERIMENTAL: DO NOT USE IN PRODUCTION YET. DO NOT RELY ON PERSISTENCE YET.
Release memory about and any exclusive locks on a single drive
and become unable to inquire or grab it.
@param drive_info pointer to a single element out of the array
obtained from burn_drive_scan() : &(drive_infos[driveno])
@return 1 on success, <=0 on failure
*/
void burn_drive_info_free(struct burn_drive_info *info);
int burn_drive_info_forget(struct burn_drive_info *drive_info);
/** Frees a burn_drive_info array returned by burn_drive_scan
*/
void burn_drive_info_free(struct burn_drive_info drive_infos[]);
/* ts A60823 */
/** Maximum length+1 to expect with a persistent drive address string */
#define BURN_DRIVE_ADR_LEN 1024
/** Inquire the persistent address of the given drive.
@param drive The drive to inquire. Usually some &(drives[driveno])
@param drive The drive to inquire. Usually some &(drive_infos[driveno])
@param adr An application provided array of at least BURN_DRIVE_ADR_LEN
characters size. The persistent address gets copied to it.
*/
@ -556,23 +574,25 @@ int burn_drive_get_adr(struct burn_drive_info *drive, char adr[]);
/** Grab a drive. This must be done before the drive can be used (for reading,
writing, etc). It may be neccesary to call this function more than once
to grab a drive. See burn_grab for details.
writing, etc).
@param drive The drive to grab. This is found in a returned
burn_drive_info struct.
@param load Nonzero to make the drive attempt to load a disc (close its
tray door, etc).
@return 1 if the drive has been grabbed, else 0
@return 1 if it was possible to grab the drive, else 0
*/
int burn_drive_grab(struct burn_drive *drive, int load);
/** Release a drive. This should not be done until the drive is no longer
busy (see burn_drive_get_status).
busy (see burn_drive_get_status). The drive is (O_EXCL) unlocked
afterwards.
@param drive The drive to release.
@param eject Nonzero to make the drive eject the disc in it.
*/
void burn_drive_release(struct burn_drive *drive, int eject);
/** Returns what kind of disc a drive is holding. This function may need to be
called more than once to get a proper status from it. See burn_status
for details.

View File

@ -89,6 +89,8 @@ struct scsi_mode_data
int underrun_proof;
};
/** Gets initialized in enumerate_common() and burn_drive_register() */
struct burn_drive
{
int host;
@ -98,6 +100,13 @@ struct burn_drive
char *devname;
int fd;
/* ts A60904 : ticket 62, contribution by elmom */
/**
Tells the index in scanned burn_drive_info array.
-1 if fallen victim to burn_drive_info_forget()
*/
int global_index;
pthread_mutex_t access_lock;
enum burn_disc_status status;