diff --git a/cdrskin/cdrskin.c b/cdrskin/cdrskin.c index 29ce4c8..9a5ad47 100644 --- a/cdrskin/cdrskin.c +++ b/cdrskin/cdrskin.c @@ -167,6 +167,7 @@ or #define Cdrskin_libburn_has_convert_fs_adR 1 #define Cdrskin_libburn_has_convert_scsi_adR 1 #define Cdrskin_libburn_has_burn_msgS 1 +#define Cdrskin_libburn_has_burn_aborT 1 #endif #ifndef Cdrskin_libburn_versioN @@ -2633,10 +2634,20 @@ int Cdrskin_release_drive(struct CdrskiN *skin, int flag) */ int Cdrskin_abort_handler(struct CdrskiN *skin, int signum, int flag) { + +#ifdef Cdrskin_libburn_has_burn_aborT + + int ret; + +#else + int wait_grain= 100000,first_status= 1; + double start_time,last_time,current_time; + +#endif /* ! Cdrskin_libburn_has_burn_aborT */ + struct burn_progress p; enum burn_drive_status drive_status= BURN_DRIVE_GRABBING; - double start_time,last_time,current_time; if(getpid()!=skin->control_pid) { if(skin->verbosity>=Cdrskin_verbose_debuG) @@ -2660,6 +2671,27 @@ int Cdrskin_abort_handler(struct CdrskiN *skin, int signum, int flag) Cdrfifo_close_all(skin->fifo,0); #endif +#ifdef Cdrskin_libburn_has_burn_aborT + + /* Only for user info */ + if(skin->grabbed_drive!=NULL) + drive_status= burn_drive_get_status(skin->grabbed_drive,&p); + if(drive_status!=BURN_DRIVE_IDLE) { + fprintf(stderr,"cdrskin: ABORT : Abort processing depends on CD speed and buffer size\n"); + fprintf(stderr,"cdrskin: ABORT : Usually it is done with 4x speed after about a MINUTE\n"); + fprintf(stderr,"cdrskin: URGE : But wait at least the normal burning time before any kill -9\n"); + } + + ret= burn_abort(skin->abort_max_wait, burn_abort_pacifier, "cdrskin: "); + if(ret<=0) { + fprintf(stderr, + "\ncdrskin: ABORT : Cannot cancel burn session and release drive.\n"); + return(0); + } + fprintf(stderr,"\n"); + +#else /* Cdrskin_libburn_has_burn_aborT */ + if(skin->grabbed_drive!=NULL) { drive_status= burn_drive_get_status(skin->grabbed_drive,&p); if(drive_status!=BURN_DRIVE_IDLE && !skin->drive_is_grabbed) @@ -2751,6 +2783,9 @@ try_to_finish_lib:; fprintf(stderr,"cdrskin: ABORT : Trying to finish libburn.\n"); burn_finish(); } + +#endif /* ! Cdrskin_libburn_has_burn_aborT */ + fprintf(stderr, "cdrskin: ABORT : Drive is released and library is shut down now.\n"); fprintf(stderr, diff --git a/cdrskin/cdrskin_timestamp.h b/cdrskin/cdrskin_timestamp.h index ba36f45..6a9346d 100644 --- a/cdrskin/cdrskin_timestamp.h +++ b/cdrskin/cdrskin_timestamp.h @@ -1 +1 @@ -#define Cdrskin_timestamP "2006.10.01.104140" +#define Cdrskin_timestamP "2006.10.02.103418" diff --git a/libburn/drive.c b/libburn/drive.c index 6ee6027..99d692d 100644 --- a/libburn/drive.c +++ b/libburn/drive.c @@ -27,9 +27,6 @@ extern struct libdax_msgs *libdax_messenger; static struct burn_drive drive_array[255]; static int drivetop = -1; -int burn_drive_is_open(struct burn_drive *d); -int burn_drive_convert_fs_adr_sub(char *path, char adr[], int *rec_count); - /* ts A60904 : ticket 62, contribution by elmom */ /* splitting former burn_drive_free() (which freed all, into two calls) */ @@ -527,13 +524,11 @@ void burn_drive_info_free(struct burn_drive_info drive_infos[]) burn_drive_free_all(); } -/* Experimental API call */ -int burn_drive_info_forget(struct burn_drive_info *info, int force) +/* ts A61001 : internal call */ +int burn_drive_forget(struct burn_drive *d, int force) { int occup; - struct burn_drive *d; - d = info->drive; occup = burn_drive_is_occupied(d); /* fprintf(stderr, "libburn: experimental: occup == %d\n",occup); @@ -556,6 +551,12 @@ int burn_drive_info_forget(struct burn_drive_info *info, int force) return 1; } +/* API call */ +int burn_drive_info_forget(struct burn_drive_info *info, int force) +{ + return burn_drive_forget(info->drive, force); +} + struct burn_disc *burn_drive_get_disc(struct burn_drive *d) { d->disc->refcnt++; @@ -954,3 +955,74 @@ int burn_drive_convert_fs_adr(char *path, char adr[]) return ret; } + +/** A pacifier function suitable for burn_abort. + @param handle If not NULL, a pointer to a text suitable for printf("%s") +*/ +int burn_abort_pacifier(void *handle, int patience, int elapsed) +{ + char *prefix= "libburn : "; + + if(handle!=NULL) + prefix= handle; + fprintf(stderr, + "\r%sABORT : Waiting for drive to finish since %d seconds (%d max)", + (char *) prefix, elapsed, patience); + return(1); +} + + +/** Abort any running drive operation and finis libburn. + @param patience Maximum number of seconds to wait for drives to finish + @param pacifier_func Function to produce appeasing messages. See + burn_abort_pacifier() for an example. + @return 1 ok, all went well + 0 had to leave a drive in unclean state + <0 severe error, do no use libburn again +*/ +int burn_abort(int patience, + int (*pacifier_func)(void *handle, int patience, int elapsed), + void *handle) +{ + int ret, i, occup, still_not_done= 1, pacifier_off= 0, first_round= 1; + unsigned long wait_grain= 100000; + time_t start_time, current_time, pacifier_time, end_time; + + current_time = start_time = pacifier_time = time(0); + end_time = start_time + patience; + while(current_time-end_time < patience) { + still_not_done = 0; + + for(i = 0; i < drivetop + 1; i++) { + occup = burn_drive_is_occupied(&(drive_array[i])); + if(occup == -2) + continue; + if(occup <= 10) { + burn_drive_forget(&(drive_array[i]), 1); + } else if(occup <= 100) { + if(first_round) + burn_drive_cancel(&(drive_array[i])); + still_not_done++; + } else if(occup <= 1000) { + still_not_done++; + } + } + first_round = 0; + + if(still_not_done == 0) + break; + usleep(wait_grain); + current_time = time(0); + if(current_time>pacifier_time) { + if(pacifier_func != NULL && !pacifier_off) { + ret = (*pacifier_func)(handle, patience, + current_time-start_time); + pacifier_off = (ret <= 0); + } + pacifier_time = current_time; + } + } + burn_finish(); + return(still_not_done == 0); +} + diff --git a/libburn/drive.h b/libburn/drive.h index 0adaa5e..a0dd4cd 100644 --- a/libburn/drive.h +++ b/libburn/drive.h @@ -52,7 +52,9 @@ void burn_disc_erase_sync(struct burn_drive *d, int fast); int burn_drive_get_block_types(struct burn_drive *d, enum burn_write_types write_type); -/* ts A60822 */ int burn_drive_is_open(struct burn_drive *d); +int burn_drive_is_occupied(struct burn_drive *d); +int burn_drive_forget(struct burn_drive *d, int force); +int burn_drive_convert_fs_adr_sub(char *path, char adr[], int *rec_count); #endif /* __DRIVE */ diff --git a/libburn/libburn.h b/libburn/libburn.h index aee20e9..5a5418f 100644 --- a/libburn/libburn.h +++ b/libburn/libburn.h @@ -391,6 +391,25 @@ int burn_initialize(void); */ void burn_finish(void); + +/** Abort any running drive operation and finally call burn_finish(). + @param patience Maximum number of seconds to wait for drives to finish + @param pacifier_func If not NULL: a function to produce appeasing messages. + See burn_abort_pacifier() for an example. + @return 1 ok, all went well + 0 had to leave a drive in unclean state + <0 severe error, do no use libburn again +*/ +int burn_abort(int patience, + int (*pacifier_func)(void *handle, int patience, int elapsed), + void *handle); + +/** A pacifier function suitable for burn_abort. + @param handle If not NULL, a pointer to a text suitable for printf("%s") +*/ +int burn_abort_pacifier(void *handle, int patience, int elapsed); + + /** Set the verbosity level of the library. The default value is 0, which means that nothing is output on stderr. The more you increase this, the more debug output should be displayed on stderr for you. diff --git a/libburn/libdax_msgs.c b/libburn/libdax_msgs.c index 0e3cc88..5f179ae 100644 --- a/libburn/libdax_msgs.c +++ b/libburn/libdax_msgs.c @@ -224,6 +224,8 @@ int libdax_msgs__text_to_sev(char *severity_name, int *severity, { if(strncmp(severity_name,"NEVER",5)==0) *severity= LIBDAX_MSGS_SEV_NEVER; + else if(strncmp(severity_name,"ABORT",5)==0) + *severity= LIBDAX_MSGS_SEV_ABORT; else if(strncmp(severity_name,"FATAL",5)==0) *severity= LIBDAX_MSGS_SEV_FATAL; else if(strncmp(severity_name,"SORRY",5)==0) @@ -253,12 +255,14 @@ int libdax_msgs__sev_to_text(int severity, char **severity_name, { if(flag&1) { *severity_name= - "NEVER\nFATAL\nSORRY\nWARNING\nHINT\nNOTE\nUPDATE\nDEBUG\nALL"; + "NEVER\nABORT\nFATAL\nSORRY\nWARNING\nHINT\nNOTE\nUPDATE\nDEBUG\nALL"; return(1); } *severity_name= ""; if(severity>=LIBDAX_MSGS_SEV_NEVER) *severity_name= "NEVER"; + else if(severity>=LIBDAX_MSGS_SEV_ABORT) + *severity_name= "ABORT"; else if(severity>=LIBDAX_MSGS_SEV_FATAL) *severity_name= "FATAL"; else if(severity>=LIBDAX_MSGS_SEV_SORRY) diff --git a/libburn/libdax_msgs.h b/libburn/libdax_msgs.h index efd10c6..0d10a68 100644 --- a/libburn/libdax_msgs.h +++ b/libburn/libdax_msgs.h @@ -121,6 +121,10 @@ struct libdax_msgs_item; */ #define LIBDAX_MSGS_SEV_FATAL 0x70000000 +/** A message from an abort handler which will finally finish libburn +*/ +#define LIBDAX_MSGS_SEV_ABORT 0x71000000 + /** A severity to exclude resp. discard any possible message. Do not use this severity for submitting. */