From c62e63a8d9d466de87d23406570021b441141775 Mon Sep 17 00:00:00 2001 From: Thomas Schmitt Date: Fri, 7 Sep 2007 19:09:25 +0000 Subject: [PATCH] Made burn_drive_scan_and_grab() extend the drive list rather than replacing it --- cdrskin/cdrskin_timestamp.h | 2 +- libburn/drive.c | 75 +++++++++++++++++++++++++++---------- libburn/libburn.h | 20 +++++----- libburn/libdax_msgs.h | 1 + 4 files changed, 68 insertions(+), 30 deletions(-) diff --git a/cdrskin/cdrskin_timestamp.h b/cdrskin/cdrskin_timestamp.h index 0793cca..daa296a 100644 --- a/cdrskin/cdrskin_timestamp.h +++ b/cdrskin/cdrskin_timestamp.h @@ -1 +1 @@ -#define Cdrskin_timestamP "2007.09.07.184631" +#define Cdrskin_timestamP "2007.09.07.190916" diff --git a/libburn/drive.c b/libburn/drive.c index a02e595..4360755 100644 --- a/libburn/drive.c +++ b/libburn/drive.c @@ -82,8 +82,10 @@ void burn_drive_free(struct burn_drive *d) return; /* ts A60822 : close open fds before forgetting them */ if (d->drive_role == 1) - if (burn_drive_is_open(d)) + if (burn_drive_is_open(d)) { + d->unlock(d); d->release(d); + } burn_drive_free_subs(d); d->global_index = -1; } @@ -782,7 +784,7 @@ int burn_drive_scan_sync(struct burn_drive_info *drives[], unsigned int *n_drives, int flag) { /* ts A70907 : - There seems to be a misunderstanding about the role of + There seems to have been a misunderstanding about the role of burn_drive_scan_sync(). It needs no static state because it is only started once during an asynchronous scan operation. Its starter, burn_drive_scan(), is the one which ends immediately @@ -792,13 +794,22 @@ int burn_drive_scan_sync(struct burn_drive_info *drives[], burn_drive_scan_sync(). The scanning itself is not parallel but enumerates sequentially drive by drive (within scsi_enumerate_drives()). + + I will use "scanned" for marking drives found by previous runs. + Leaving it static for now, but initializing it on each call by + iterating over the list of known drives. */ - /* state vars for the scan process */ /* ts A60904 : did set some default values to feel comfortable */ - static int scanning = 0, scanned = 0, found = 0; + static int scanning = 0; + /* ts A70907 : + These variables are too small anyway. We got up to 255 drives. + static int scanned = 0, found = 0; + Variable "found" was only set but never read. + */ + static unsigned char scanned[32]; static unsigned num_scanned = 0, count = 0; - unsigned int i; + int i; /* ts A61007 : moved up to burn_drive_scan() */ /* a ssert(burn_running); */ @@ -815,16 +826,26 @@ int burn_drive_scan_sync(struct burn_drive_info *drives[], state */ #endif /* 0 */ - /* ts A70907 : moved here from burn_drive_info_free() */ - if (flag & 1) + *n_drives = num_scanned = 0; + + /* ts A70907 : wether to scan from scratch or to extend */ + if (flag & 1) { burn_drive_free_all(); + for (i = 0; i < sizeof(scanned); i++) + scanned[i] = 0; + } else { + for (i = 0; i <= drivetop; i++) + if (drive_array[i].global_index >= 0) { + scanned[i / 8] |= (1 << (i % 8)); + num_scanned++; + } + } /* refresh the lib's drives */ /* ts A61115 : formerly sg_enumerate(); ata_enumerate(); */ scsi_enumerate_drives(); - *n_drives = scanned = found = num_scanned = 0; count = burn_drive_count(); if (count) { /* ts A70907 : @@ -840,23 +861,23 @@ int burn_drive_scan_sync(struct burn_drive_info *drives[], scanning = 0; return -1; } else - (*drives)[count].drive = NULL; /* end mark */ + for (i = 0; i <= count; i++) /* invalidate */ + (*drives)[i].drive = NULL; } else *drives = NULL; } for (i = 0; i < count; ++i) { - if (scanned & (1 << i)) - continue; /* already scanned the device */ + if (scanned[i / 8] & (1 << (i % 8))) + continue; /* device already scanned by previous run */ while (!drive_getcaps(&drive_array[i], - &(*drives)[num_scanned])) { + &(*drives)[*n_drives])) { sleep(1); } - scanned |= 1 << i; - found |= 1 << i; - num_scanned++; (*n_drives)++; + scanned[i / 8] |= 1 << (i % 8); + num_scanned++; } if (num_scanned == count) { @@ -1140,9 +1161,21 @@ int burn_drive_scan_and_grab(struct burn_drive_info *drive_infos[], char* adr, int load) { unsigned int n_drives; - int ret; + int ret, i; - /* >>> check wether drive adress is already registered */ + /* check wether drive adress is already registered */ + for (i = 0; i <= drivetop; i++) + if (drive_array[i].global_index >= 0) + if (strcmp(drive_array[i].devname, adr) == 0) + break; + if (i <= drivetop) { + libdax_msgs_submit(libdax_messenger, i, + 0x0002014b, + LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, + "Drive is already registered resp. scanned", + 0, 0); + return -1; + } if(strncmp(adr, "stdio:", 6) == 0) { ret = burn_drive_grab_dummy(drive_infos, adr + 6); @@ -1156,7 +1189,7 @@ int burn_drive_scan_and_grab(struct burn_drive_info *drive_infos[], char* adr, adr); */ -/* ts A70907 : now calling synchronously rather than looping */ + /* ts A70907 : now calling synchronously rather than looping */ ret = burn_drive_scan_sync(drive_infos, &n_drives, 0); if (ret < 0) return -1; @@ -1164,7 +1197,11 @@ int burn_drive_scan_and_grab(struct burn_drive_info *drive_infos[], char* adr, if (n_drives <= 0) return 0; /* - fprintf(stderr, "libburn: experimental: n_drives == %d\n",n_drives); + fprintf(stderr, "libburn: experimental: n_drives %d , drivetop %d\n", + n_drives, drivetop); + if (n_drives > 0) + fprintf(stderr, "libburn: experimental: global_index %d\n", + drive_infos[0]->drive->global_index); */ ret = burn_drive_grab(drive_infos[0]->drive, load); diff --git a/libburn/libburn.h b/libburn/libburn.h index cba20b6..ea5055b 100644 --- a/libburn/libburn.h +++ b/libburn/libburn.h @@ -626,12 +626,6 @@ void burn_allow_untested_profiles(int yes); 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() - - <<< Restriction in progress of being removed: - To avoid memory leaks or dangling pointers one MUST shutdown all - burn_drive_info arrays by burn_drive_info_free() before calling - burn_drive_scan() a second time. - You are *strongly urged* to use this call whenever you know the drive address in advance. If not, then you have to use directly above calls. In that case, you are @@ -642,6 +636,11 @@ void burn_allow_untested_profiles(int yes); use the function described here with an address obtained after burn_drive_scan() via burn_drive_get_adr(&(drive_infos[driveno]), adr) . Another way is to drop the unwanted drives by burn_drive_info_forget(). + + Other 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 hold aquired more than one drive at a time. + @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. @@ -675,13 +674,14 @@ void burn_drive_clear_whitelist(void); /** Scan for drives. This function MUST be called until it returns nonzero. - No drives may be in use when this is called. + In case of re-scanning: All pointers to struct burn_drive and all struct burn_drive_info arrays are invalidated by using this function. Do NOT store drive pointers across calls to this function ! - To avoid memory leaks or dangling pointers one MUST shutdown all - burn_drive_info arrays by burn_drive_info_free() before calling - bunr_drive_scan() a second time. + To avoid invalid pointers one MUST free all burn_drive_info arrays + by burn_drive_info_free() before calling burn_drive_scan() a second time. + If there are drives left, then burn_drive_scan() will refuse to work. + 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(). diff --git a/libburn/libdax_msgs.h b/libburn/libdax_msgs.h index 64af8e4..ac15829 100644 --- a/libburn/libdax_msgs.h +++ b/libburn/libdax_msgs.h @@ -383,6 +383,7 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff 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 + 0x0002014b (SORRY,HIGH) = Drive is already registered resp. scanned libdax_audioxtr: